TwinEthosRequest access

Control

Protected or proxy attribute reaches AI decision

AI decisions about people must not be driven by protected traits or their proxies.

Informational data, not legal advice. Summaries are TwinEthos's own words and rules have not been reviewed by a lawyer: check the official text before relying on any of it. A guard addresses an item; adding it is not a statement that your code meets any law.

Family: AI is used without bias, fairness, or proxy-discrimination controls · control id cond.protected-or-proxy-attribute-in-ai-decision

Reach

4items this one guard addresses
3jurisdictions where binding law on it is in force
0more where it is enacted, not yet applying
1standards and frameworks on the same control

Law in force in Colorado (US-CO), Illinois (US-IL), Texas (US-TX).

The guard to add

Build decision prompts and feature sets from an allowlist of decision-relevant fields, and redact protected attributes, known proxies, and free text before the model sees them.

At the prompt builder or feature-assembly step on the consequential-decision path, construct model inputs from an explicit allowlist (FEATURE_ALLOWLIST, APPROVED_FEATURES) instead of passing the whole person record or f-string interpolating its fields. Protected attributes (race, sex, religion, age, disability) and proxies (ZIP or postal code, surname, school, census tract) stay out unless a documented justification and a bias test exist, and free text (cover letters, notes, transcripts) goes through redaction (redact_pii, strip_protected_attributes) first. Log the features used and the model output per decision, and run disparity tests on outcomes; human review lowers the risk but does not replace the allowlist.

Where it goes: 1 application source code, 2 data models, 7 prompt construction, 13 tests and evals.

What reviewers look for: an allowlist or redaction function between the person record and the prompt or model.predict call; no f-string or template literal that interpolates zip, race, gender, age, surname, or school into a decision prompt; a justification record for any personal attribute that is kept; a per-decision input log; disparity tests (fairlearn MetricFrame, disparate_impact) on outcomes.

Example (Python + OpenAI SDK), before:

prompt = f"Applicant {a.last_name}, age {a.age}, zip {a.zip_code}.\nNotes: {a.applicant_notes}\nApprove the loan?"
resp = client.chat.completions.create(model=MODEL, messages=[{'role': 'user', 'content': prompt}])

After:

FEATURE_ALLOWLIST = ['income', 'debt_to_income', 'requested_amount', 'payment_history_months']

features = {k: getattr(a, k) for k in FEATURE_ALLOWLIST}
notes = strip_protected_attributes(a.applicant_notes)   # drops names, ages, places, etc.
messages = [{'role': 'system', 'content': LENDING_RUBRIC},
            {'role': 'user', 'content': json.dumps({'features': features, 'notes': notes})}]
resp = client.chat.completions.create(model=MODEL, messages=messages)
decision_log.record(a.id, features, resp.choices[0].message.content)

Engineering guidance, not legal advice. Each provision below may add its own details (a cadence, a deadline, a required notice element): open it for those.

Every rule this guard addresses

Binding law — in force (3)

Standard / soft law (1)

Related incidents

No guardrail sits on this exact control; these incidents are cited by guardrails on related controls.