Skip to main content

Security posture

Built for trust, not for show

We're not a security company, but ConKarma holds the kind of data — kids, partners, daily rituals — that demands honest answers about how we protect it. This page is the unvarnished version.

Last reviewed:

How sign-in works

We treat your password as a secret we never see in cleartext, store the strongest hash the spec gives us, and rotate refresh tokens so a stolen cookie can't outlive the session it came from.

  • Passwords are hashed with argon2id (RFC 9106 m=19 MiB profile). Older bcrypt-hashed passwords are upgraded transparently the next time you sign in — no forced password resets.
  • Sessions use rotating refresh-token families. If a stolen token is replayed, the whole family invalidates and the legitimate device is forced to re-auth — no silent compromise.
  • Configurable account lockout after repeated failed attempts. Cleared automatically once you sign in correctly, so a typo never traps you out.
  • Sign in with Apple and Sign in with Google use direct OpenID Connect — goia_api connects to Apple and Google itself, with no third-party auth broker in the path. We receive only the upstream provider identifier, your email, and the verified flag — never your provider password.

Sign-in security

Every sign-in passes through a second factor. Every new-device sign-in alerts you. Parents are kept in the loop for under-18s without leaking anything else.

  • Two-factor authentication at every sign-in: 6-digit code via email, 30-day trusted-device window so repeat sign-ins on the same device don’t re-prompt.
  • Real-time email alert when your account is accessed from a new device: device type, approximate city + country, timestamp. One tap revokes that device and forces a password reset.
  • Under-18 users’ sign-ins from new devices also alert parent-role members of their cell. Transparent: minors see in Settings exactly which parents are wired up to receive these alerts.
  • Backup codes: 8 single-use codes at first setup, accessible from Settings → Security, regenerate on demand. Recovery path when email access is lost.
  • Password storage: argon2id, the industry-standard memory-hard hash. Trusted-device tokens are separate from session tokens — losing one doesn’t compromise the other.
  • Rate-limited verification: 5 failed code attempts triggers a 15-minute lockout. Keeps a stolen email address from being a free brute-force target.

When something looks off

If a sign-in arrives from a country we haven't seen on your account in the last 30 days, we email you. The email has a one-click "this wasn't me" that revokes the session and walks you straight into a password reset.

  • Unknown-location email alerts (one per country per 30-day window — a vacation doesn't spam you).
  • Active-sessions list with per-device revoke from inside the app. You can sign out a lost phone without changing your password.
  • Failed-sign-in detail (timestamp, country code only — never raw IP) visible inside the app's security log.

Real apps only

Mobile traffic is attested as coming from a real ConKarma install on a real device. Curl-against-the-API attempts get soft-rejected, which is what an honest API surface should do.

  • Firebase App Check on iOS and Android. The token is required on every API call from mobile.
  • Mobile TLS pinning via the signed manifest at /.well-known/mobile-pins.json. New pins are signed by an offline key and rotated with a six-week overlap window so an upgrade can't lock anyone out.

Adult-tier features are off-limits to analytics

ConKarma has two zones: a Serene zone (everything family-friendly) and an Ember zone (the 18+ adult-tier features). Ember pages deliberately do not fire third-party analytics events. We collect aggregate Prometheus counters server-side for capacity and uptime; nothing more.

  • Adult-tier surfaces (dares, desires, fantasies, intimate journals, the private vault) never load Google Analytics.
  • Biometric unlock is required to enter Ember surfaces in the app. The system will time out and re-lock if you switch apps.
  • Screenshot guard hides Ember content from the OS app-switcher and any screen-recording overlays.
  • Per-device adult-zone enable: default ON for your primary device, OFF for every other one. You explicitly opt in per device, and the server-side check fails closed.
  • Inactivity re-prompt: the biometric latch drops after 5 minutes of inactivity inside Ember, or 30 seconds of backgrounded dwell. Both are configurable from Settings → Privacy.
  • In-memory cache zeroing: when you cross from Ember back to Serene (or background the app), every cached image is dropped from memory — defense in depth against memory-inspection tooling.
  • Spotlight, Apple Intelligence, and AppIntents exclusion: no adult content is ever donated to Spotlight, the on-device LLM, AppIntents, Smart Stack, or Lock Screen widgets.
  • Two-eye admin access: no human at XTZ Group can read adult-zone content unilaterally — every override requires a second admin's signed approval, written to an immutable audit log.
  • Configurable 3-year adult retention: adult-zone rows are auto-deleted after 3 years by default. The window is user-configurable (90 days to 10 years) from Settings → Privacy. Hard-delete once the window elapses.
  • iCloud Backup and GDPR-export controls: two opt-in toggles in Settings → Privacy keep adult content out of device backups and out of your data export by default — so accidentally shared backups or exports don't expose it.

Read the full zone-isolation guarantees →

Consent infrastructure + conflict tools

Hard conversations and adult-zone consent both go through structured, curated surfaces — never an AI pipeline. The data behind them stays local or couple-private; nothing about a safeword activation or a sibling repair leaves the device pair, and our admins can't read it.

  • Conflict tools — AI pipeline excluded: every sibling, couple, and cross-generational repair flow is curated content + structured forms. The text a kid taps is from our editorial set, not a model. The text a partner sees in a repair frame is from a fixed prompt library. We don't route any of it through an LLM — for privacy, calibration, and agency reasons explained in detail on the blog.
  • Consent infrastructure — Ember: the limits doc, the safeword binding, and the aftercare check-ins live on Ember E2E primitives — separate keypair, biometric-gated, never replicated to any server-side analytics. The limits doc never reaches our AI pipeline. Safeword activations write a couple-private log entry that stays on the device pair. Aftercare check-in answers are couple-private.
  • Personal-hide + cell-level controls: when you hide a feature for yourself, the BE doesn't delete the underlying data — it stays intact so the surface re-appears the moment you flip it back. Cell-owner toggles work the same way. Any permanent-flag operation that actually destroys data requires a two-eye admin gate, written to an immutable audit log.

Ember consent infrastructure

Adult-tier surfaces don't ship with a generic 'I agree' checkbox and call it consent. Ember is structured around three load-bearing primitives — the limits document, the safeword, and aftercare check-ins — that live on the same E2E keypair as the rest of the adult zone. Mature framing throughout; agency, not paternalism.

  • Limits document: each partner builds and edits their own, viewable only by the other partner in the same couple cell. Never reaches our analytics pipeline; never read by any AI; never replicated server-side beyond the encrypted blob.
  • Safeword binding: one couple-shared safeword phrase that immediately drops every Ember surface back to Serene + writes a couple-private log row. Activations are visible to both partners only; XTZ Group operators can't read them.
  • Aftercare check-ins: scheduled by either partner after an Ember session, opt-in per partner, answers stay couple-private. No engagement counter, no streak, no nag.
  • Mature framing: copy and prompts treat adult readers as adults. We do not infantilise the surfaces with euphemisms; we also don't lean on shock value to feel transgressive.

Double-blind consent matching

When two partners explore which fantasy categories overlap, the matching runs entirely on-device with two structural invariants we will not break: never-reveal-no (if either partner taps no, neither sees that fact) and zero-egress AI (no model anywhere in the inference path).

  • Never-reveal-no invariant: a yes/yes pair surfaces in the shared match list. Any other combination (yes/no, no/yes, no/no) returns nothing — neither partner sees who said no, and neither sees that the other was even shown the prompt. This is anti-pressure structural design, not a setting you can flip off.
  • Zero-egress AI invariant: the matching computation is a local set intersection. No model inference, no embedding lookup, no AI scoring of categories or pairings. The set of categories itself is curated editorial content, not generated.
  • Couple-private results: the match list is end-to-end encrypted to the couple's shared keypair. Server-side we see counts (capacity planning) but never the categories themselves.
  • Auditable invariants: the two invariants above are enforced in the on-device code path with no toggles and no admin override. A platform operator cannot opt a couple in to telemetry on this surface — there is no telemetry to opt in to.

Take It Down Act compliance — public notice channel

The federal TAKE IT DOWN Act (2025) requires platforms hosting user content to act on takedown requests for non-consensual intimate imagery within 48 hours. ConKarma's public notice channel + procedure is published at /legal/takedown-notice; this section is the security-posture summary.

  • Channel: legal@conkarma.app (subject line Take It Down notice / DMCA notice / Urgent — CSAM report).
  • Commitment: 48-hour SLA from receipt of a valid request to removal or disabling of access.
  • Coverage: NCII (real or AI-generated deepfakes), DMCA copyright, CSAM (elevated priority + NCMEC report), and broader unlawful-content reports.
  • Counter-notice: DMCA counter-notice path through the same channel; statutory 10–14 business day restoration window in the absence of a court order.
  • Audit: every notice + every action taken is logged and preserved for the periods required by law. Bad-faith notices may expose the sender to civil liability under the Act, DMCA §512(f), and our Terms.

Per-state regulatory dial

Where US states or other jurisdictions pass laws that constrain what a platform can offer (age verification regimes, content-category restrictions, recordkeeping mandates), we adjust behaviour regionally rather than retreat from the market. The honest tradeoff: a state's law shapes what the surface looks like for users in that state, not what we believe is right product design.

  • Region detection: based on the user's stated country + (for the US) the state they've configured in Settings, not IP geolocation alone. Users can override the inferred region if it's wrong.
  • What gets adjusted: age-verification flows (KOSA-style states), adult-content gating, retention windows where state law dictates them, and disclosure copy where the state requires specific phrasing.
  • What does NOT get adjusted: end-to-end encryption posture, the zero-egress AI invariants, the COPPA-compliant default for under-13, and the never-mix-adult-content-rows table invariant. Those are non-negotiable across jurisdictions.
  • Transparency: the regional configuration applied to your account is visible in Settings → Privacy → Regional posture. If you think it's wrong for your jurisdiction, file a Take It Down notice or write to legal@conkarma.app.

Kids are not a growth lever

Under-13 accounts go through a verifiable parental-consent flow before they exist. We don't show ads on child accounts, full stop. We don't sell child data, share it for advertising, or use it to target anything.

  • COPPA §312.5-compliant verifiable parental consent (signed credit-card-holder verification path, with a fallback for non-card households).
  • No third-party advertising of any kind on accounts under 13.
  • Parents can view, export, and erase their child's account data at any time from inside the app.

Trust comes from the Cell, not from us

ConKarma is a closed-circle product. There are no public profiles, no follower graphs, and no way to discover strangers. Most moderation happens because you and the people in your Cell already know and trust each other. Where the model needs help, we have a report flow and a moderation queue with a human in it.

  • Cells are closed by default. No public discovery, no public profile, no friend-of-friend suggestions.
  • User-report flow on every content surface, routed to a moderation queue worked by humans.
  • Hash-based scanning for known CSAM is tracked as a known-and-pending implementation, with explicit revisit triggers when we move to a media-storage profile that requires it. We won't claim it before it's real.

What we keep, where, and how to get it back

We over-document this on /privacy and /legal/subprocessors, but the security-relevant short version is: encrypted at rest, stored where the SCC paperwork covers it, exportable and erasable on demand, and we don't keep more than we need.

  • GDPR, CCPA, and Quebec-25 export and erasure controls live inside the app — not behind a support ticket. Erasure has a 30-day soft-delete grace window in case you change your mind.
  • Encryption at rest on the Postgres database and on object storage (Supabase-managed infrastructure).
  • Raw IP addresses are not stored on any user-facing surface. The active-sessions list shows only a 2-letter country code; raw IPs exist briefly in security-event rows for forensic use under a short retention window.

If you find something, tell us

We don't run a paid bug-bounty yet — that's a real gap and we'll move on it once it earns the operator time it needs. In the meantime we welcome good-faith reports and will acknowledge them within five business days.

Email: security@conkarma.app

  • Email security@conkarma.app with details. PGP key on request.
  • We commit to acknowledging within 5 business days and substantive response within 30 days.
  • Coordinated disclosure: 90-day default window before public disclosure, extendable by mutual agreement.
  • We will not pursue legal action against good-faith security research that follows responsible disclosure.