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

# Security & data handling

> What Phosra collects per object, how long it keeps it, how to erase it against a real endpoint, encryption in transit and at rest, data residency, the subprocessor list, and how to report a vulnerability.

Phosra handles children's data, so the bar is higher than "we take security seriously." This
page is the **developer-facing reference**: exactly which fields each object stores, how long
they live, how to erase them **against a real endpoint you can call right now**, how data is
encrypted, where it lives, who the subprocessors are, and how to report a vulnerability.

<Note>
  **One source of truth.** The authoritative, always-current security posture — subprocessor
  list, DPA, SOC 2 status, incident history — lives at the
  **[Phosra Trust Center](https://www.phosra.com/trust)**. This page mirrors it for developers
  and adds the runnable erasure flow. Where a claim is forward-looking rather than
  code-verifiable today, it is tagged <Badge color="yellow">policy preview</Badge>.
</Note>

## Data minimization — collect the least that works

Phosra is a **control plane for parental-controls policy**, not a data lake. It stores the
metadata needed to compile and enforce a policy, and nothing it does not need. The
[core object model](/concepts/data-model) is the whole surface — there is no hidden
telemetry object.

### What each object stores

<AccordionGroup>
  <Accordion title="Family — the household root" icon="house" defaultOpen>
    | Field                       | Classification  | Why it's collected                                                                              |
    | --------------------------- | --------------- | ----------------------------------------------------------------------------------------------- |
    | `id`                        | Identifier      | Primary key.                                                                                    |
    | `name`                      | Low-sensitivity | Household display name (e.g. *"The Rivera Family"*). Free-text — not validated as a legal name. |
    | `created_at` / `updated_at` | Metadata        | Lifecycle timestamps.                                                                           |

    No address, no payment data, no location. A family is a container.
  </Accordion>

  <Accordion title="FamilyMember — a guardian on the account" icon="user">
    | Field                   | Classification | Why it's collected                                                      |
    | ----------------------- | -------------- | ----------------------------------------------------------------------- |
    | `id`                    | Identifier     | Primary key.                                                            |
    | `family_id` / `user_id` | Identifier     | Links a guardian's authenticated user to the household.                 |
    | `role`                  | Metadata       | `owner` · `parent` · `guardian` — drives who may change or delete what. |
    | `joined_at`             | Metadata       | Audit timestamp.                                                        |

    The parent's **login identity** (email) is held by the auth provider
    ([WorkOS](https://www.phosra.com/trust#subprocessors)), stored hashed, and referenced here
    only by `user_id`. Phosra's product tables do not store the parent's raw email.
  </Accordion>

  <Accordion title="Child — a kid's profile" icon="child">
    This is the most sensitive object. It is deliberately thin.

    | Field                       | Classification  | Why it's collected                                                                                                              |
    | --------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------- |
    | `id`                        | Identifier      | Primary key.                                                                                                                    |
    | `family_id`                 | Identifier      | Foreign key → `Family`.                                                                                                         |
    | `name`                      | **PII (child)** | First name / display name only. No surname is required.                                                                         |
    | `birth_date`                | **PII (child)** | Drives the age band and rule defaults. This is the *reason* Phosra exists — an age-appropriate policy is impossible without it. |
    | `avatar_url`                | Optional        | Parent-supplied image URL; nullable and usually `null`.                                                                         |
    | `created_at` / `updated_at` | Metadata        | Lifecycle timestamps.                                                                                                           |

    **Never collected on a child:** device identifiers tied to advertising, precise geolocation,
    biometrics, contacts, browsing history, or message content. Enforcement happens against
    *categories*, not against a log of what the child did.
  </Accordion>

  <Accordion title="ChildPolicy + PolicyRule — the ruleset" icon="shield">
    Policy state is configuration, not behavior. A `PolicyRule` records **which of the
    [123 OCSS categories](/concepts/policies-and-rules) is on** and its config — never an event
    that a rule fired against a specific child action.

    | Object        | Sensitive fields | Notes                                                                                                   |
    | ------------- | ---------------- | ------------------------------------------------------------------------------------------------------- |
    | `ChildPolicy` | none             | `name`, `status`, `priority`, `version`.                                                                |
    | `PolicyRule`  | none             | `category`, `enabled`, `config`. Category config is policy intent (e.g. `max_ratings`), not child data. |
  </Accordion>

  <Accordion title="Enforcement + audit — the durable record" icon="clipboard-check">
    | Object                                 | What it holds                                                                                                                                | Retention driver                           |
    | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
    | `EnforcementJob` / `EnforcementResult` | Which policy was pushed to which platform, and the per-platform outcome. Provider response payloads are captured in `details` for debugging. | Operational + regulatory defensibility.    |
    | Audit log                              | Every enforcement decision — rule, input, output, statute citation — on a durable event stream.                                              | Compliance reporting; see retention below. |

    The **data-plane** `EnforcementReceipt` is **identity-free by construction** — no child ref,
    device id, or user id (see [Data model → EnforcementReceipt](/concepts/data-model)). The
    router that moves OCSS signals **cannot decrypt the payload it carries**; the envelope is
    sealed to the recipient's key. See [Content monitoring](/integration/content-monitoring).
  </Accordion>
</AccordionGroup>

### What Phosra never does with child data

<CardGroup cols={2}>
  <Card title="No sale or brokering" icon="ban">
    Minor data is never sold, rented, or brokered — ever.
  </Card>

  <Card title="No ad targeting" icon="ban">
    Child data is never used for advertising or ad targeting, and never shared with ad
    networks or data brokers.
  </Card>

  <Card title="No external model training" icon="ban">
    Child data is never used to train external ML models.
  </Card>

  <Card title="No content logging" icon="ban">
    Phosra enforces against categories. It does not keep a log of a child's messages,
    browsing, or activity.
  </Card>
</CardGroup>

## Retention

| Data class                   | Default retention                                                       | Configurable?                                |
| ---------------------------- | ----------------------------------------------------------------------- | -------------------------------------------- |
| Child profile + policy state | Life of the account; erased on parent-initiated deletion (below).       | Yes — parent-initiated erasure at any time.  |
| Enforcement + audit logs     | Retained only as long as required for regulatory defensibility.         | <Badge color="yellow">policy preview</Badge> |
| Backups                      | Purged on the standard backup-rotation cycle after a live-store delete. | <Badge color="yellow">policy preview</Badge> |

Retention windows are **parent-configurable**, and defaults follow the **most conservative
applicable statute** (COPPA / UK AADC). The exact numeric windows and the backup-rotation
period are governed by the DPA rather than the API — request them from
[security@phosra.com](mailto:security@phosra.com) for a security review. They are tagged
<Badge color="yellow">policy preview</Badge> here because they are not readable from the
sandbox or OpenAPI spec.

## Right to erasure — a real, runnable flow

Erasure is not a support ticket. Deleting a `Family` **cascades** to every `Child`,
`ChildPolicy`, `PolicyRule`, and enforcement record beneath it, and deleting a single `Child`
erases just that child's subtree. Both are ordinary `DELETE` calls that return **`204 No
Content`**.

<Info>
  Every request and response below was **captured live** against the public sandbox
  `https://phosra-api-sandbox-production.up.railway.app` on 2026-07-06 — so you can run this
  end-to-end right now. In production these routes require your `phosra_live_…` key and an
  owner/parent role on the family. See [Authentication](/authentication) and
  [Environments](/concepts/environments).
</Info>

### Erase a single child

`DELETE /children/{childID}` removes the child profile and its entire policy subtree.

<CodeGroup>
  ```bash cURL theme={null}
  # childID from when you created the child (or POST /setup/quick)
  curl -i -X DELETE "$PHOSRA_BASE_URL/children/e6e094ee-de89-4dc2-98b2-cd3c3a28309e"
  # → HTTP/2 204
  ```

  ```typescript TypeScript theme={null}
  const BASE = "https://phosra-api-sandbox-production.up.railway.app/api/v1";

  async function eraseChild(childId: string) {
    const res = await fetch(`${BASE}/children/${childId}`, { method: "DELETE" });
    // 204 No Content — the child and its policies/rules are gone.
    if (res.status !== 204) throw new Error(`unexpected ${res.status}`);
  }

  await eraseChild("e6e094ee-de89-4dc2-98b2-cd3c3a28309e");
  ```

  ```python Python theme={null}
  import requests

  BASE = "https://phosra-api-sandbox-production.up.railway.app/api/v1"

  def erase_child(child_id: str) -> None:
      res = requests.delete(f"{BASE}/children/{child_id}", timeout=30)
      res.raise_for_status()  # 204 No Content
      assert res.status_code == 204

  erase_child("e6e094ee-de89-4dc2-98b2-cd3c3a28309e")
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"net/http"
  )

  const base = "https://phosra-api-sandbox-production.up.railway.app/api/v1"

  func main() {
  	req, _ := http.NewRequest(http.MethodDelete,
  		base+"/children/e6e094ee-de89-4dc2-98b2-cd3c3a28309e", nil)
  	res, _ := http.DefaultClient.Do(req)
  	defer res.Body.Close()
  	fmt.Println(res.StatusCode) // 204
  }
  ```
</CodeGroup>

**Verify it's gone** — a read of the erased child returns `404`, not a soft-deleted tombstone:

```bash theme={null}
curl -s "$PHOSRA_BASE_URL/children/e6e094ee-de89-4dc2-98b2-cd3c3a28309e"
# → 404  {"error":"Not Found","message":"child not found","code":404}
```

### Erase the whole household (cascade)

`DELETE /families/{familyID}` erases the family **and everything beneath it in one call** —
proven live: a child created under the family reads `404` immediately after the family delete.

<CodeGroup>
  ```bash cURL theme={null}
  curl -i -X DELETE "$PHOSRA_BASE_URL/families/ec5bc0d7-e02c-42f8-b821-c71d926f27d2"
  # → HTTP/2 204

  # The child that lived under it is now gone too:
  curl -s -o /dev/null -w "%{http_code}\n" \
    "$PHOSRA_BASE_URL/children/d48d0260-1881-449e-98f8-7aa21dae546c"
  # → 404
  ```

  ```typescript TypeScript theme={null}
  const BASE = "https://phosra-api-sandbox-production.up.railway.app/api/v1";

  async function eraseFamily(familyId: string) {
    const res = await fetch(`${BASE}/families/${familyId}`, { method: "DELETE" });
    if (res.status !== 204) throw new Error(`unexpected ${res.status}`);
    // Every child, policy, rule, and enforcement record under it is erased.
  }

  await eraseFamily("ec5bc0d7-e02c-42f8-b821-c71d926f27d2");
  ```

  ```python Python theme={null}
  import requests

  BASE = "https://phosra-api-sandbox-production.up.railway.app/api/v1"

  def erase_family(family_id: str) -> None:
      res = requests.delete(f"{BASE}/families/{family_id}", timeout=30)
      res.raise_for_status()  # 204 — cascades to children, policies, rules

  erase_family("ec5bc0d7-e02c-42f8-b821-c71d926f27d2")
  ```

  ```go Go theme={null}
  req, _ := http.NewRequest(http.MethodDelete,
  	base+"/families/ec5bc0d7-e02c-42f8-b821-c71d926f27d2", nil)
  res, _ := http.DefaultClient.Do(req)
  defer res.Body.Close()
  fmt.Println(res.StatusCode) // 204
  ```
</CodeGroup>

<Note>
  **Removing one guardian, not the household:** to detach a single parent/guardian without
  erasing anyone's data, use `DELETE /families/{familyID}/members/{memberID}` (also `204`).
  That removes the person's access; it does not delete the children.
</Note>

### Data portability / export

Machine-readable **JSON exports** for portability (GDPR Art. 20 / CCPA) are available **on
request** — email [security@phosra.com](mailto:security@phosra.com). There is **no self-serve
export endpoint on the API today** (a `GET …/export` returns `404`) — we say so plainly rather than imply one
exists. A self-serve export API is <Badge color="yellow">policy preview</Badge>.

## Encryption

<CardGroup cols={2}>
  <Card title="In transit — TLS 1.3 + HSTS" icon="lock">
    HTTPS is enforced end-to-end with TLS 1.3; HSTS at the edge. A conservative
    Content-Security-Policy restricts script, frame, form, base, object, and worker sources.
    Plain-HTTP requests are redirected, never served.
  </Card>

  <Card title="At rest — AES-256-GCM" icon="database">
    Postgres with tenant scoping enforced at the application layer on **every** query.
    AES-256-GCM is applied to sensitive fields (OAuth tokens, provider credentials) on top of
    standard at-rest disk encryption.
  </Card>

  <Card title="Sealed data-plane envelope" icon="eye-slash">
    OCSS signals are sealed **end-to-end to the recipient's key**. The routing layer reads
    only the headers it needs to move a signal — the router structurally cannot decrypt the
    payload. See [Content monitoring](/integration/content-monitoring).
  </Card>

  <Card title="Short-lived auth" icon="key">
    Production auth runs on WorkOS with short-lived JWTs and a **separate sandbox tenant** for
    development. Admin actions are gated behind explicit role checks on every request.
  </Card>
</CardGroup>

## Data residency & subprocessors

**US-primary data residency** across all subprocessors. Phosra updates this list when the
data path changes; the [Trust Center](https://www.phosra.com/trust#subprocessors) is the
authoritative copy.

| Subprocessor | Purpose                                 | Region                 |
| ------------ | --------------------------------------- | ---------------------- |
| Supabase     | Postgres database + object storage      | US                     |
| Railway      | API compute (`phosra-api`)              | US                     |
| Vercel       | Edge CDN + Next.js hosting              | Global edge, US origin |
| WorkOS       | Authentication (JWT / AuthKit)          | US                     |
| Sentry       | Error tracking + performance monitoring | US                     |
| Resend       | Transactional email                     | US                     |

Need the signed subprocessor DPA for your vendor review? Request it at
[security@phosra.com](mailto:security@phosra.com).

## Regulatory alignment

Phosra maps its controls to the statutes that govern children's data. Conformance is
**evidence a regulator can weigh — not an approval Phosra issues, and not a safe harbor.**

| Framework                                                                        | How Phosra aligns                                                                                                               |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **COPPA / COPPA 2.0**                                                            | Verifiable parental consent, minimum-necessary collection, and parent-initiated deletion are built into the enforcement engine. |
| **GDPR-K / GDPR** (Art. 8 child consent, Art. 17 erasure, Art. 33 breach notice) | Erasure is a live `DELETE` (above); breach notification within 72 hours; data-minimized child object.                           |
| **UK AADC** (Age-Appropriate Design Code)                                        | High-privacy defaults, no profiling, no nudges — enforceable policies in the registry, not documentation wishes.                |
| **KOSA**                                                                         | Duty-of-care surfaces mapped across the OCSS rule categories.                                                                   |
| **EU DSA** (Art. 28)                                                             | Minor-protection obligations supported via queryable audit trails and transparency-report-ready exports.                        |
| **CCPA / CPRA**                                                                  | No sale/share of minor data; deletion and portability honored.                                                                  |

See the [compliance hub](https://www.phosra.com/compliance) for the per-statute detail pages.

## Report a vulnerability

Phosra welcomes good-faith security research.

<Steps>
  <Step title="Email security@phosra.com" icon="envelope">
    Send findings to **[security@phosra.com](mailto:security@phosra.com)**. We triage within
    **one business day** and keep you updated through remediation.
  </Step>

  <Step title="Stay in scope" icon="shield-halved">
    Don't access data that isn't your own, don't test against production parent or child
    accounts, and don't run scanners that degrade service. **Use the open
    [sandbox](/concepts/environments)** for testing — it holds only synthetic data.
  </Step>

  <Step title="Coordinated disclosure" icon="handshake">
    Give us a reasonable window to remediate before public disclosure. With your permission,
    we credit researchers in our disclosure log.
  </Step>
</Steps>

<Warning>
  **Incident response.** On a confirmed incident Phosra follows a documented playbook —
  contain, assess, notify, remediate — with breach notification **within 72 hours** of
  confirmation, consistent with **GDPR Article 33** and **CCPA**. Affected parents are contacted
  directly via the email of record.
</Warning>

## Where to go next

<CardGroup cols={2}>
  <Card title="Trust Center →" icon="shield-check" href="https://www.phosra.com/trust" horizontal>
    The authoritative, verifiable security & governance posture.
  </Card>

  <Card title="Core objects & data model →" icon="sitemap" href="/concepts/data-model" horizontal>
    Every field of every object this page classifies.
  </Card>

  <Card title="Environments →" icon="layer-group" href="/concepts/environments" horizontal>
    Sandbox vs. production, and why the sandbox holds only synthetic data.
  </Card>

  <Card title="Authentication →" icon="key" href="/authentication" horizontal>
    Keys, roles, and the owner/parent gate on destructive calls.
  </Card>
</CardGroup>
