> ## Documentation Index
> Fetch the complete documentation index at: https://docs.modulex.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Trust & data handling

> How ModuleX handles, isolates, and retains your data: per-organization tenancy, credentials encrypted at rest, redacted logs, and an audit trail, plus where compliance details live.

export const MediaEmbed = ({id, type = 'screenshot', caption = '', ext, ratio = '16 / 9'}) => {
  const isVideo = type === 'video' || type === 'app_video';
  const resolvedExt = ext || (isVideo ? 'mp4' : type === 'screenshot' ? 'webp' : 'svg');
  const src = 'https://media.modulex.dev/' + id + '.' + resolvedExt;
  const [status, setStatus] = useState('loading');
  const [isDev, setIsDev] = useState(false);
  const [inView, setInView] = useState(false);
  const boxRef = useRef(null);
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const h = window.location.hostname;
    setIsDev(h === 'localhost' || h === '127.0.0.1' || h.endsWith('.mintlify.app'));
  }, []);
  useEffect(() => {
    if (inView) return;
    if (typeof IntersectionObserver === 'undefined') {
      setInView(true);
      return;
    }
    const el = boxRef.current;
    if (!el) return;
    const io = new IntersectionObserver(entries => {
      if (entries.some(e => e.isIntersecting)) {
        setInView(true);
        io.disconnect();
      }
    }, {
      rootMargin: '300px'
    });
    io.observe(el);
    return () => io.disconnect();
  }, [inView]);
  if (status === 'missing') {
    if (!isDev) return null;
    return <div style={{
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'center',
      gap: '0.4rem',
      padding: '1rem 1.25rem',
      margin: '1.25rem 0',
      width: '100%',
      aspectRatio: ratio,
      boxSizing: 'border-box',
      border: '1px dashed rgba(128,128,128,0.45)',
      borderRadius: '0.75rem',
      background: 'rgba(128,128,128,0.06)',
      color: 'currentColor',
      fontSize: '0.85rem',
      lineHeight: 1.45
    }}>
        <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '0.5rem',
      opacity: 0.75
    }}>
          <span aria-hidden="true">🎬</span>
          <code style={{
      fontSize: '0.75rem'
    }}>{id}</code>
          <span style={{
      fontSize: '0.65rem',
      textTransform: 'uppercase',
      letterSpacing: '0.04em',
      padding: '0.1rem 0.4rem',
      borderRadius: '0.4rem',
      background: 'rgba(128,128,128,0.18)'
    }}>
            {type}
          </span>
        </div>
        <div style={{
      opacity: 0.9
    }}>{caption || 'Media not uploaded yet.'}</div>
        <div style={{
      fontSize: '0.7rem',
      opacity: 0.5
    }}>
          Upload to R2 as <code>{id}.{resolvedExt}</code> — preview only, hidden in production.
        </div>
      </div>;
  }
  const mediaStyle = {
    display: status === 'loaded' ? 'block' : 'none',
    width: '100%',
    height: 'auto',
    borderRadius: '0.75rem'
  };
  const media = isVideo ? <video src={inView ? src : undefined} autoPlay loop muted playsInline preload="metadata" onLoadedData={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} /> : <img src={inView ? src : undefined} alt={caption} onLoad={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} />;
  return <figure style={{
    margin: '1.25rem 0'
  }}>
      <div ref={boxRef} style={status === 'loaded' ? {
    width: '100%'
  } : {
    width: '100%',
    aspectRatio: ratio,
    borderRadius: '0.75rem',
    background: 'rgba(128,128,128,0.06)'
  }}>
        {media}
      </div>
      {status === 'loaded' && caption ? <figcaption style={{
    marginTop: '0.5rem',
    textAlign: 'center',
    fontSize: '0.85rem',
    opacity: 0.7
  }}>
          {caption}
        </figcaption> : null}
    </figure>;
};

When you run a workflow on ModuleX, your data passes through it: the documents in your knowledge bases, the credentials that connect your tools, and the records of what ran and when. This page explains, in plain language, how ModuleX handles that data, how it keeps each organization's data separate, and how long it is kept.

For the engineering mechanics behind these promises, see [Security overview](/security/overview). For certifications and the third parties involved, see [Compliance](/security/compliance) and [Sub-processors](/security/sub-processors).

<CardGroup cols={3}>
  <Card title="Kept separate" icon="box" href="#every-organization-is-its-own-boundary">
    Every workflow, credential, and document belongs to exactly one organization, and stays there.
  </Card>

  <Card title="Handled with care" icon="lock" href="#how-your-data-is-handled">
    Connected credentials are encrypted, sensitive values are hidden from logs, and secrets are never shown back in full.
  </Card>

  <Card title="Kept only as needed" icon="clock" href="#how-long-data-is-kept">
    Your records live as long as your organization does. Delete the organization and its data is removed with it.
  </Card>
</CardGroup>

## Every organization is its own boundary

In ModuleX, an [organization](/concepts/organizations-roles) is the unit that owns your work and the line that separates it from everyone else's. Your workflows, runs, credentials, knowledge bases, chats, plan, and bill all live inside one organization.

<CardGroup cols={2}>
  <Card title="One owner per record" icon="fingerprint">
    Every resource you create is stamped with its organization. There is no shared pool, and one organization's data is never visible to another.
  </Card>

  <Card title="Checked on every request" icon="user-check" href="/security/org-context">
    Org-scoped requests carry the `X-Organization-ID` header. ModuleX confirms you belong to that organization, and your role in it, before it runs anything, not just at sign-in.
  </Card>

  <Card title="Keys can be locked to one org" icon="lock" href="/security/authentication">
    An API key scoped to a single organization cannot act on another, even if it is shared by mistake. ModuleX rejects the request.
  </Card>

  <Card title="No cross-org reads" icon="shield">
    Every read and write is filtered by organization, so a query can only ever return the data of the organization the request runs in.
  </Card>
</CardGroup>

Because the organization is the boundary, tenancy isolation is something ModuleX enforces on every database read and write, not a setting you have to turn on. For exactly how the organization header is checked and how a key is bound to one organization, see [Org context & X-Organization-ID](/security/org-context).

<MediaEmbed id="MX-MEDIA-4260" type="image" caption={"A diagram showing two organizations as separate sealed boxes, each containing its own workflows, credentials, knowledge bases, and bill, with no line crossing between them."} />

## How your data is handled

ModuleX holds a small set of things worth protecting: the credentials that connect your tools, the documents you upload, and the logs of what happened. Each is handled differently.

<Tabs>
  <Tab title="Connected credentials">
    When you connect a service, ModuleX stores a [credential](/concepts/credentials-oauth): an encrypted record that lets your workflows act on your behalf.

    * The secret part of every credential is encrypted before it is written to the database, with a key derived for that one credential in that one organization.
    * A credential is decrypted in memory only at the moment a workflow or agent needs it, then used to call the connected service.
    * When you view a credential in the app or through the API, ModuleX returns a masked value such as `start***end`, never the secret in full.

    The encryption and key-management details are documented for engineers in [Data security & encryption](/security/data-encryption).
  </Tab>

  <Tab title="Your documents">
    Files you add to a knowledge base are stored so they can be retrieved when a chat or workflow needs them. See [Knowledge & RAG](/concepts/knowledge-rag) for how retrieval works and [Managing documents](/platform/knowledge/documents) for upload limits.

    * Document storage is pluggable: a ModuleX-managed deployment can keep files in managed cloud object storage, and a self-hosted deployment can keep them on its own disk.
    * Documents, like everything else, belong to one organization and are only ever retrieved within it.
  </Tab>

  <Tab title="Logs & secrets">
    ModuleX writes operational logs to run the service and help you debug, but it is built not to leak secrets into them.

    * Known sensitive fields, including `password`, `token`, `secret`, `api_key`, `credentials`, `access_token`, and `refresh_token`, are redacted from logs.
    * Logged request bodies are capped in size, so large payloads are not stored in full.
    * API keys are kept as a one-way hash, not a recoverable value, so even ModuleX cannot read them back. The full key is shown only once, when you create it.
  </Tab>
</Tabs>

<Accordion title="What does &#x22;encrypted at rest&#x22; mean for my credentials?">
  Each stored credential is encrypted with a key unique to that credential and its organization, derived from a master encryption key that ModuleX keeps as a managed secret. Because the per-credential key depends on both the organization and the credential, ciphertext from one credential cannot be unlocked as another, even within the same organization. ModuleX requires that master secret to be present and strong before it will start in a production environment, and it can be sourced from a managed secret store. The full rules are in [Data security & encryption](/security/data-encryption).
</Accordion>

<Accordion title="Does ModuleX use my data to train models?">
  This is a data-handling commitment, not a code-level fact, so it is not asserted here. **TBD** — confirm ModuleX's stance on using customer data for model training on the [Compliance](/security/compliance) page before relying on it. When you bring your own model provider, that usage runs under your provider's terms; see [LLM providers](/integrations/llm-providers/overview).
</Accordion>

## How long data is kept

Your records are kept for as long as you need them, and removed when your organization is.

<CardGroup cols={2}>
  <Card title="Active for as long as your org is" icon="infinity">
    Workflows, runs, credentials, knowledge bases, and chats stay available while your organization exists, so your history and your connected tools keep working.
  </Card>

  <Card title="Removed when the org is deleted" icon="trash">
    Deleting an organization removes the data tied to it, including its workflows, runs, credentials, knowledge bases, and wallet records.
  </Card>
</CardGroup>

<Note>
  When an organization is deleted, its records are removed as a group. Some history that records who did something keeps the action but unlinks the person, so removing a teammate's account does not erase the record that an action occurred. The exact relationships are documented in the [Data model reference](/reference/data-model).
</Note>

### The audit trail

ModuleX keeps a unified audit log per organization that records important actions: who did something, what they did, and when. It exists so an organization can review activity for accountability and compliance.

* The configured retention for the audit log is **365 days** (one year).
* Audit entries are scoped to the organization, like every other record.

<Note>
  The 365-day figure is the audit-log retention configured in ModuleX. Whether older entries are automatically purged on a managed deployment, and any contractual retention or deletion commitments, are not asserted here. **TBD** — confirm the operative retention and deletion terms on the [Compliance](/security/compliance) page or in your agreement.
</Note>

## Compliance posture

ModuleX's compliance details, including any certifications and audits, data residency, and the formal data processing terms, are maintained on dedicated pages rather than asserted here, so the information you rely on is the current, verified version.

<Warning>
  This page does not claim any specific certification (such as SOC 2, ISO 27001, GDPR alignment, or HIPAA), data-residency region, or signed data processing agreement. **TBD** — those claims are unverified at the time of writing. Check the pages below, or contact the ModuleX team, before relying on any compliance statement.
</Warning>

<CardGroup cols={2}>
  <Card title="Compliance" icon="clipboard-check" href="/security/compliance">
    ModuleX's compliance posture, certifications, and data-residency details.
  </Card>

  <Card title="Sub-processors" icon="building" href="/security/sub-processors">
    The third parties that may process data on ModuleX's behalf, and how changes are announced.
  </Card>
</CardGroup>

## Where to go next

<CardGroup cols={3}>
  <Card title="Security overview" icon="shield-check" href="/security/overview">
    The plain-language tour of how ModuleX secures access, credentials, and tenancy.
  </Card>

  <Card title="Data security & encryption" icon="lock" href="/security/data-encryption">
    How credentials are encrypted at rest, plus key management and production checks.
  </Card>

  <Card title="Roles & permissions" icon="user-shield" href="/security/roles-permissions">
    The owner and admin roles, and which actions each can take.
  </Card>
</CardGroup>
