# FERPA / COPPA scope (/docs/use-cases/education/ferpa-coppa)



This page is for the procurement conversation. Read it before
signing a district agreement that names FERPA or COPPA as the
governing framework.

## TL;DR [#tldr]

`@pleach/compliance` profiles that ship today are
`"hipaa" | "gdpr" | "pci-dss" | "soc2"`. There is no `ferpa` or
`coppa` profile literal. The
[`educationAgent`](/docs/use-cases/education) factory accepts
the education-facing strings (`ferpa`, `coppa`, `ferpa+coppa`)
and substitutes the `gdpr` profile bundle as the closest shipped
analog. The substitution is recorded on the runtime tag, fires a
`warn-once` notice to your console, and is documented in the
factory JSDoc. It is **not** full FERPA or COPPA adequacy.

## What you DO get when you pass `ferpa+coppa` [#what-you-do-get-when-you-pass-ferpacoppa]

1. **The student-safety scrubber** runs against the user message
   string before the runtime sees it. See
   [Student safety](/docs/use-cases/education/student-safety)
   for the redaction patterns (student-id numbers, grade bands,
   school-issued emails, labeled parent-contact lines).
2. **The `gdpr` profile bundle** runs on top of the
   student-safety scrubber. The `gdpr` bundle today is
   `SsnUsScrubber + CreditCardScrubber` — see
   [`compliantChatbot` config](/docs/recipes/compliant-chatbot)
   for the canonical bundle mapping. The substitution is the
   closest shipped analog because FERPA and COPPA both lean
   heavily on data-minimization plus identifier redaction, and
   the `gdpr` bundle is the data-minimization scrubber stack we
   ship today.
3. **A per-session cost-cap policy** registered on the runtime
   so a runaway loop in a classroom can be cut off at the
   gateway boundary (see
   [Per-district tenant + cost-cap](/docs/use-cases/education/per-district-tenant)).
4. **An audit ledger** (when you wire
   [`@pleach/compliance/audit`](/docs/audit-ledger)) that
   records every event with a `tenantId` you can scope to
   `districtId` and pull at end-of-year for retention review.
5. **Substitution transparency**: the runtime tag carries both
   `requestedProfile` (what you asked for) and `mappedProfile`
   (what the substrate applied). Your audit ledger can record
   both. A district auditor can see at row level that the
   `gdpr` bundle was applied because `ferpa+coppa` was
   requested.

## What you DO NOT get [#what-you-do-not-get]

These are the items that would belong in a full FERPA / COPPA
posture and are NOT shipped today.

### FERPA-specific gaps [#ferpa-specific-gaps]

* **Directory Information mediation.** FERPA distinguishes
  "directory information" (name, address, phone, dates of
  attendance — disclosable unless the parent has opted out) from
  protected educational records. The shipped scrubber redacts
  conservatively on identifier shape (IDs, grade bands,
  school-issued emails); it does not consult a per-student
  directory-information opt-out registry. If your buyer needs
  per-student opt-out enforcement, wire it as a pre-`ask()`
  classifier or as a custom `Scrubber`.
* **Educational-record retention rules.** FERPA retention is
  state-by-state and district-by-district. The audit ledger
  records `recordedAt` so you can prune on a schedule, but the
  retention policy itself is operator-owned. No built-in
  retention enforcement.
* **Vendor data-processing addendums (DPAs).** Pleach does not
  ship a FERPA-equivalent vendor DPA. If your buyer's
  procurement requires one, you'll need to author it; the
  audit-ledger + scrubber evidence in this stack supports a
  DPA but does not constitute one.
* **Joint custodial / parent-of-record gating.** FERPA rights
  transfer to the student at the age of majority OR upon
  enrollment in a post-secondary institution. The runtime tag
  records `studentId`; it does NOT enforce a parent-of-record
  identity gate. The consumer's auth layer owns that.

### COPPA-specific gaps [#coppa-specific-gaps]

* **Verifiable Parental Consent (VPC) flow.** COPPA Section
  312.5 requires verifiable parental consent before collecting
  personal information from a child under 13. Pleach does not
  ship a VPC flow (no parental-credit-card verification, no
  signed-consent-form intake, no government-ID check). The
  consumer-facing application is the consent boundary.
* **Under-13 age gating.** No age-of-user determination layer.
  If your platform admits under-13 users, your front door
  decides whether COPPA applies; Pleach treats every session as
  identical at the data plane.
* **Safe-harbor program enrollment.** Pleach is not enrolled in
  a COPPA Safe Harbor program (kidSAFE, iKeepSafe, ESRB, etc.).
* **Operator-vs-school-official classification.** COPPA permits
  school-authorized collection of PI without parental consent
  under the "school-official" doctrine when the school has
  designated the vendor as a school official under FERPA. That
  designation is contractual — Pleach does not assert it on
  your behalf.

### Cross-framework gaps [#cross-framework-gaps]

* **No State-Student-Privacy-Pledge co-signature.** Major
  districts increasingly require vendors to co-sign the Student
  Privacy Pledge (studentprivacypledge.org). Pleach has not
  signed it.
* **No formal FERPA / COPPA compliance attestation.** The
  `@pleach/compliance` audit ledger surfaces hash-chained
  evidence usable in an attestation; an attestation report
  itself is operator-authored.
* **Model providers may not be configured for education
  workloads.** OpenAI, Anthropic, and Google Vertex each have
  separate enterprise terms that may or may not be appropriate
  for under-13 data. Pleach does not enforce a per-provider
  age-of-data gate. If your provider's standard terms forbid
  under-13 data, you must route around that contractually
  (e.g. enterprise contract, BYOK with a provider whose terms
  permit it, or a self-hosted model).

## What the `warn-once` notice says [#what-the-warn-once-notice-says]

When you construct an `educationAgent` with a `complianceProfile`,
the factory logs:

```
[educationAgent] requested compliance profile 'ferpa+coppa' is
not yet shipped — mapped to 'gdpr' (closest shipped analog). See
module JSDoc honest scope-limit.
```

The warning fires once per process (latched). It is intentional
— suppressing it hides a substitution that procurement should
see. If you want the warning routed to your audit ledger instead
of stderr, wrap the factory and rewrite `console.warn` for that
construction call.

## How to compose a stronger posture today [#how-to-compose-a-stronger-posture-today]

If you need to ship to a district that gates the buy on FERPA /
COPPA evidence and can't wait for a dedicated profile cut, three
patterns compose well on top of `educationAgent`:

1. **Pre-`ask()` content moderation API.** Wire Anthropic /
   OpenAI moderation, or a kid-safety classifier (e.g. a
   self-hosted toxicity model), as a pre-`ask()` filter. Reject
   the turn before the model sees it on a category flag.
2. **District-extended scrubber.** Pass an `extra` patterns
   array on `createStudentSafetyScrubber` (see
   [Student safety](/docs/use-cases/education/student-safety))
   to redact district-specific identifiers — SIS IDs, locker
   numbers, IEP filenames — the shipped scrubber doesn't know
   about.
3. **EventLogWriter-boundary scrubbing.** Compose a
   `ComplianceRuntime` directly (as
   [`compliantChatbot`](/docs/recipes/compliant-chatbot) does
   internally) and pass `host.modules.eventLogWriter` so the
   persisted copy of every event row is scrubbed at the
   substrate boundary too. The `educationAgent` factory does
   NOT do this automatically today; the scrubbing is at the
   user-message boundary only.

## Roadmap [#roadmap]

A dedicated `ferpa-coppa` compliance profile cut is on the
education wave. The shape it will likely take:

* A `ferpa+coppa` scrubber bundle distinct from `gdpr`:
  student-safety scrubber + parent / guardian PII patterns +
  school-staff PII patterns + state-program identifiers (free /
  reduced lunch, IEP, 504-plan numbers).
* A per-event-type allowlist tuned for classroom-transcript
  shapes (`tutor.turn`, `feedback.recorded`,
  `assignment.draft`) in addition to the generic
  `content.delta` / `interrupt.edited` / `audit.recorded`
  allowlist `compliantChatbot` ships with today.
* An optional VPC stub that records consent evidence on the
  audit ledger (consumer-supplied; the substrate does not
  perform verification).

Until that cut ships, the `educationAgent` factory makes the
substitution explicit so it can be cited cleanly in a procurement
review. The factory will continue to accept `ferpa` / `coppa` /
`ferpa+coppa` after the dedicated profile ships — the runtime
tag's `mappedProfile` will then read `ferpa-coppa` instead of
`gdpr`.

## Source [#source]

* `packages/recipes/src/education.ts` — substitution map and
  `warn-once` latch.
* `packages/compliance/src/runtime/` — the `ComplianceRuntime`
  and shipped profile bundles.

## See also [#see-also]

* [Education](/docs/use-cases/education) — the landing page.
* [Student safety](/docs/use-cases/education/student-safety) —
  the shipped scrubber.
* [Per-district tenant + cost-cap](/docs/use-cases/education/per-district-tenant) —
  multi-tenant composition for districts.
* [`compliantChatbot`](/docs/recipes/compliant-chatbot) — the
  HIPAA / GDPR / PCI-DSS / SOC 2 sibling recipe.
* [`@pleach/compliance`](/docs/compliance) — the full
  compliance reference.
* [Audit ledger](/docs/audit-ledger) — hash-chained evidence
  for compliance review.
