Skip to main content

Student Privacy

Use student-privacy for a narrow check of student-record terms and student ID phrases. It can block or mark a request for redaction. It has limited non-streaming response behavior.

This policy is not a FERPA or COPPA compliance engine. It does not verify identity, consent, school context, jurisdiction, or record status.

Outcome

Input evaluation

ConditionVerdictCause code
No student markerallowstudent_privacy.clean
Marker found, default action: redactredactstudent_privacy.redact
Marker found with action: blockblockstudent_privacy.block
Marker found with an age less than 13 and age_gate: trueblockstudent_privacy.age_gate

Input details contain action, age_gate, under_13, student_id_like, and the first keyword_hit match.

Output handling

The action and response transport control output behavior:

ConfigurationActive non-streaming behavior
action: redactThe gateway's response-redaction pass replaces student-ID-like patterns in supported OpenAI JSON fields.
action: blockThe gateway blocks supported responses containing student id, transcript, ferpa, or a student ID/identifier/number phrase with student_privacy.block.

An output block returns an HTTP 400 policy-violation response. It does not return the provider body.

Prerequisites

  • Add student-privacy to the effective global or route chain.
  • Select block when delivery must stop on a detected input marker.
  • Use redact only after you test the specified identifiers that the gateway must replace.
  • Use it with pii-detector or dlp-filter when broader personal or institutional data coverage is necessary.

Configuration

pack:
name: student-privacy-example-1
version: "1.0.0"
enabled: true

policies:
chain:
- student-privacy

policy:
student-privacy:
action: redact
age_gate: true

Supported fields

FieldTypeDefaultNotes
actionstringredactredact or block.
age_gatebooleanfalseWhen enabled, it blocks a student marker when the first inline age is from 1 through 12.

Specified input detection

The evaluator makes one string from message text and does case-insensitive checks for:

DetectorValues
Built-in termsstudent id, student_id, transcript, iep, 504 plan, grade, gpa, disciplinary, ferpa
ID phrasestudent id, student identifier, or student number, optional :, #, or -, then a minimum of four letters, digits, or hyphens
Inline ageage N or N years old, where N has one or two digits

An age expression does not trigger the policy alone. It changes the action only with a built-in term or student ID match.

Examples:

TextDefault resultWith age_gate: true
Help an age 12 learner with fractions.allowallow. Age alone is not a marker.
Student ID: AB-1234redactredact
Student ID: AB-1234, age 12redactblock with student_privacy.age_gate
Send the transcript.redactredact

age_gate reads only message text. It does not use account profiles, headers, verified birth dates, or consent records. It has no different level for ages less than 18.

Redaction boundary

The input evaluator returns redact for a built-in term or ID match. The gateway redactor has one student-identifier pattern. It matches a student ID, identifier, or number with a minimum of four characters.

Consequently:

  • Student ID: AB-1234 can be replaced by the redaction pass.
  • A term such as send the transcript causes redact. By itself, it has no student-identifier replacement target.
  • The policy result does not show redaction targets. The gateway redaction path reports applied replacements.

Do not use a redact verdict as proof that the gateway removed each student term. Verify the returned and forwarded payloads.

For non-streaming output, the gateway adds the same student ID pattern to its response redactor. A changed response has nested cause pii.detected. Its last cause is redact.applied when the policy type is student-privacy.

Output boundary

The output block detector has fewer terms than the input detector. It does not check iep, 504 plan, grade, gpa, or disciplinary.

Streaming behavior is also different. The SSE path does not run the student output-block evaluator. Its general redaction buffer does not prove that each student-specific marker was changed.

Use stream: false whenever student output enforcement is necessary. Input blocks continue to occur before provider calls.

Test input behavior

Create tests/blocks-under-13-student-record.json:

{
"name": "blocks-under-13-student-record",
"input": {
"messages": [
{
"role": "user",
"content": "Student ID: AB-1234 and age 12."
}
]
},
"expected": {
"verdict": "block",
"reason_code": "student_privacy.age_gate"
}
}

Use this config while running that fixture:

policy:
student-privacy:
action: redact
age_gate: true

Then run:

verdictan policy lint --file policy-config.yaml
verdictan policy test --json

Add these related cases as a minimum:

  • Clean education content gives allow and ok.
  • A student ID at age 13 gives redact and redact.applied.
  • A transcript-only request gives redact and redact.applied.
  • The same marker with action: block gives block and student_privacy.block.

verdictan policy test runs the input evaluator. Use a running gateway to verify response redaction, response blocks, and stream behavior.

Rollout checklist

  1. Make a list of student identifiers and record terms in your traffic.
  2. Identify if a marker must block or use the redaction path.
  3. Add matching, nonmatching, age-control, and false-match fixtures.
  4. Test non-streaming responses for redaction and block behavior.
  5. Also test stream: true if the application enables it.
  6. Deploy to a limited route or gateway.
  7. Correlate typical request IDs with verdictan events tail --since 10m --json.
  8. Review false matches for broad substrings such as grade and gpa.

Troubleshooting

SymptomLikely causeResolution
An age-12 request was allowedNo student marker matched, age_gate was off, or a different earlier age expression was parsed.Include a supported marker and test the specified message text.
A transcript request says redact but text is unchangedKeyword detection caused the verdict, but the student redactor only has an ID-like replacement pattern.Use block if the complete request must stop, or add a supported DLP/PII control.
Output with grade was not blockedOutput block detection uses a smaller marker set.Test against the documented output terms or use a different supported output control.
Streamed output was not blocked or changedSSE does not give the documented student output contract.Use stream: false for necessary student output enforcement.
Policy is not shown in resultsIt is not in the effective chain or is skipped by conditions/targeting.Examine the applied route chain and targeting context.
Team uses the policy as FERPA/COPPA certificationThe policy is a deterministic text control only.Complete the broader legal, consent, identity, retention, and usage controls external to this policy.

Next steps