Security & data-handling overview
Audience: security reviewers, CISOs, compliance and procurement teams evaluating a product built on the CMC platform. This is a factual engineering statement of posture, not marketing and not legal advice. Operators: have your counsel review this alongside your own Terms of Service and Privacy Policy before relying on it contractually — those legal documents are yours, not CMC's.
Identity & authentication
- Identity is delegated to a dedicated OIDC provider (Zitadel, self-hosted per deployment). Application surfaces never receive or store passwords; sessions are server-side with opaque HttpOnly/Secure cookies. MFA is available to every account.
- Service-to-service and client authorization uses short-lived signed JWTs; messaging-layer permissions are per-connection NATS JWTs minted from a deployment-local signing chain (decentralized operator model). Offline/edge credentials are pre-minted, signed, and verifiable without a network round trip.
- Authorization is attribute-based, computed mechanically from platform claims. Per-user isolation is enforced at the message broker on every publish/subscribe — subject-level grants, not application-side checks.
Federated sign-in
- Operators may offer sign-in with external providers (Google and Microsoft today). The provider authenticates the person to the platform's own identity provider, which remains the only token issuer applications see.
- Linking requires the account's own credential. At sign-in, an external sign-in is connected to an existing account only after that account's password is presented. A signed-in person can also connect one from their account's security settings, after confirming it is them (password or passkey) and completing the provider's sign-in. A matching email address alone never links accounts, and the sign-in pages never reveal whether an account exists for an address. Automatic linking is not configurable on.
- Microsoft sign-ins are never treated as email-verified (the multi-tenant endpoint carries no verification signal), so they never find an account by email and new Microsoft users verify their address by code. Any provider's new user can instead connect an existing account by signing in to it ("Already have an account? Sign in to connect"), through the sign-in form's own uniform refusal and timing.
- Where an email does find an account, the verified holder of the address is preferred; without one, only a single unverified holder counts, and anything ambiguous is no match. An account whose email is unverified cannot gain a provider connection at sign-in unless that provider vouches for the same address (ADR-0023 amendment, pre-hijack hardening).
- A verified address belongs to one account. Every step that verifies an address (a code, a provider that vouches, an address switch) checks it, and only after the mailbox is proven, so the answer naming the existing account reaches only the mailbox's owner. Verifying an address removes it from every account that merely claimed it; such an account is asked for a new address at its next sign-in. Password-reset requests by email go only to the one account the address identifies.
- MFA still applies after the provider. An account with an authenticator app enrolled is asked for its code after an external sign-in, exactly as after a password; the provider's own authentication does not satisfy the platform's second factor.
- An account cannot remove its last way to sign in. Provider client secrets are held in Kubernetes Secrets and never appear in configuration values or logs. Operator detail: federated-login.md.
Encryption & data at rest
- In transit: TLS on all public surfaces; broker connections authenticated per-connection.
- At rest: user content (messages, posts, media) is stored platform-readable by design — content moderation (report review) and channel bridging (re-rendering messages into external networks) require it. No end-to-end encryption is claimed anywhere in the product, and product copy is required to state this posture verbatim: transport-encrypted, platform-readable.
- Media is stored by reference in an object store; access honors the referencing content's visibility on every request.
Payments (PCI scope)
- All card handling is delegated to Stripe (Elements/hosted surfaces + Connect for seller payouts). Primary account numbers and CVCs never transit or persist on platform systems — stored-card references are Stripe tokens plus display metadata (brand, last4, expiry). Target PCI posture: SAQ-A.
- Off-session charges require explicit recorded consent per stored card; charge outcomes are returned as platform-defined categories, never raw processor declines.
Moderation & administrative access
- Reports snapshot content at report time; snapshots are reviewable by the moderators of the owning organization (org-scoped content) or platform operators (platform-scoped content).
- Every moderation action lands in an append-only ledger (actor, authority, action) with UPDATE/DELETE revoked at the database layer.
- Removed content is tombstoned (structure-preserving marker), never silently deleted.
- Direct messages are not accessible to organization staff; they enter review only via a participant's report.
Abuse & availability controls
- Per-user sliding-window rate limits on every write surface; per-address rate limits on unauthenticated inbound (bridge pairing).
- Notification delivery is storm-controlled by design: signature deduplication, escalating digest windows, hard per-recipient channel budgets, and a circuit breaker that collapses event floods into a single updating notification.
- Services are distroless containers with health probes, structured audit-grade logging (correlation IDs), and self-describing introspection manifests.
Subprocessors & external networks
- Stripe — payment processing and seller payouts.
- Optional, per deployment: Telegram (bridged messaging), Slack (planned), Twilio/SMS (planned), an email provider (when enabled). Bridged messages traverse the chosen external network under that network's own terms; users opt in per channel and can revoke pairing at any time. Unpaired external senders are inert.
Disclosure
Security contact: the operator of this deployment. Reports are welcomed; please include reproduction detail. (Operators: set this value in your deployment's branding/config.)