lakehouse/docs/policies/consent/biometric_consent_template_v1.md
root b2c34b80b3 phase 1.6: lock Gate 3b = C, reconcile docs to shipped state, fix double-upload file leak
Four threads landing together — all driven by the audit J asked for before
production cutover.

(1) Gate 3b DECIDED: Option C (defer classifications). `BiometricCollection.classifications`
    stays `Option<JSON> = None` in v1. `docs/specs/GATE_3B_DEEPFACE_DESIGN.md` status
    flipped from "draft / awaits product" to DECIDED. Consent template + retention
    schedule revised to remove all "automated facial-classification" / "deepface"
    language so disclosed scope matches implemented scope.

(2) Endpoint-path drift reconciled across 3 docs. `PHASE_1_6_BIPA_GATES.md`,
    `BIPA_DESTRUCTION_RUNBOOK.md`, and `biometric_retention_schedule_v1.md` had
    references to legacy `/v1/identity/subjects/*` paths (proposed under a separate
    identityd daemon, never shipped) — corrected to actual shipped routes
    `/biometric/subject/*` (catalogd-local). Schema block in PHASE_1_6_BIPA_GATES
    rewritten to reflect JSON `SubjectManifest.biometric_collection` substrate
    (not the proposed Postgres `subjects` table).

(3) New operational artifacts:
    - `scripts/staffing/verify_biometric_erasure.sh` — checks 4 things post-erasure
      (manifest cleared, uploads dir empty, audit row matches, chain verified).
      Smoke-tested live against WORKER-2.
    - `scripts/staffing/biometric_destruction_report.sh` — monthly anonymized
      destruction-event aggregation. Smoke-tested clean.
    - `scripts/staffing/bundle_counsel_packet.sh` — tarballs the counsel-review
      packet with per-file SHA-256 manifest.
    - `docs/runbooks/LEGAL_AUDIT_KEY_ROTATION.md` — formal rotation procedure
      operationalized after the 2026-05-05 /tmp wipe incident.
    - `docs/counsel/COUNSEL_REVIEW_PACKET_2026-05-05.md` — cover note bundling
      all eng-staged BIPA docs for counsel review with per-doc questions, sign-off
      checklist, recommended review sequence.

(4) Double-upload file leak fixed in `crates/catalogd/src/biometric_endpoint.rs`.
    `verify_biometric_erasure.sh` smoked WORKER-2 and surfaced a stranded photo
    file. Investigation showed the file was 13-byte test-fixture bytes (zero PII,
    no biometric content); audit timeline showed two consecutive uploads followed
    by one erasure — the second upload had silently overwritten manifest.data_path,
    orphaning the first file. Patched `process_upload` to refuse a second upload
    with HTTP 409 + `error: "biometric_already_collected"` when
    `biometric_collection.is_some()` on the manifest. Operator must explicitly
    POST `/biometric/subject/{id}/erase` first.

    Tests: new `second_upload_without_erase_returns_409` (asserts 409 + manifest
    pointer unchanged + first file untouched on disk). Replaced
    `repeated_uploads_grow_the_chain` with `upload_erase_upload_grows_the_chain_cleanly`
    (covers the legitimate re-collection cycle: chain grows to 3 rows). Updated
    `content_type_with_parameters_accepted` to use 2 distinct subjects (was
    using 1 subject with 2 uploads to test ct parsing — would now 409).

    22/22 biometric_endpoint tests + 59/59 catalogd lib tests green post-patch.

Production posture: gateway needs `cargo build --release -p gateway` +
`systemctl restart lakehouse.service` to pick up the new 409 in live traffic.

Counsel calendar is now the only remaining blocker for first real-photo intake.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 06:19:40 -05:00

176 lines
6.6 KiB
Markdown

# Biometric Information Consent — v1
**Spec:** docs/PHASE_1_6_BIPA_GATES.md §1 Gate 2 (BIPA §15(b)(1)-(3))
**Status:** Engineering scaffold — ⚖ COUNSEL must author the binding text before deployment
**Version:** v1 (initial; supersession requires a new version + new hash)
**Updated 2026-05-05:** Disclosure 1 + plain-language summary revised to match the Gate 3b deferral recommendation in `docs/specs/GATE_3B_DEEPFACE_DESIGN.md` (Option C — defer classifications). Pending J's product confirmation of Gate 3b; if Gate 3b chooses Option A or B, this template needs counsel re-authoring.
> This is the consent template a candidate signs (electronically or
> on paper) BEFORE Lakehouse collects, stores, or processes any
> biometric identifier or biometric information from that candidate.
>
> Without an executed consent under this template (or a counsel-
> approved successor), the system MUST NOT accept a photograph from
> the candidate. Enforcement lives at the photo-upload endpoint
> (Gate 3) and at the SubjectManifest writer, which refuses biometric
> writes when `consent.biometric.status != "given"`.
---
## Required disclosures (BIPA §15(b)(1)-(3))
The disclosures below are MANDATORY content per 740 ILCS 14/15(b).
⚖ COUNSEL — render this content into binding language appropriate
for the candidate-facing UI. Engineering provides the structural
content; counsel provides the legally-sufficient wording.
### Disclosure 1 — Notice of collection (§15(b)(1))
Lakehouse will collect and store my **biometric identifier** (a
photograph of me from which facial geometry is implicit). The
photograph itself is the data we keep — we do NOT run automated
facial-classification (gender / race / age inference) against it
in v1. If at a later date we add automated classification, we will
re-collect consent under a superseding template before doing so.
### Disclosure 2 — Specific purpose and length of term (§15(b)(2))
The biometric data will be used for:
1. Identity verification at staffing job sites
2. Internal record-keeping so coordinators can recognize me across
placements
The biometric data will be retained for a maximum of **18 months**
from my most recent interaction with the staffing platform, after
which it will be permanently destroyed per the
[Biometric Retention Schedule v1](biometric_retention_schedule_v1.md).
I may withdraw this consent at any time by contacting the operator
(see §3 below). Withdrawal triggers permanent destruction of my
biometric data.
### Disclosure 3 — Written release (§15(b)(3))
I provide a written release authorizing Lakehouse to collect, store,
and use my biometric identifier and biometric information for the
purposes stated above and for the term stated above.
---
## 1. Plain-language summary (non-binding)
⚖ COUNSEL — the section above is the binding legal disclosure.
The summary below is provided for candidate comprehension and is
NOT a substitute for the binding disclosure. Both should appear
together in the consent UI; counsel determines whether this summary
is appropriate to include or whether a different plain-language
section is preferred.
> **What you're agreeing to:** if you upload a photo of yourself,
> we'll keep that photo so your staffing coordinator can recognize
> you when you arrive at job sites. We don't run automated guesses
> about your age, gender, or race against the photo.
>
> **How long we keep it:** at most 18 months after your last
> placement or interaction with us, then it's permanently destroyed.
>
> **What we DON'T do with it:** we don't sell it, we don't share it
> with anyone outside the staffing operation unless legally compelled,
> and we don't use it to decide what jobs to recommend to you.
>
> **How to take it back:** contact us (§3 below) at any time to
> withdraw your consent. We will permanently destroy your biometric
> data within 30 days of receiving your request.
---
## 2. Withdrawal procedure
I may withdraw biometric consent at any time. Withdrawal:
- Is free of charge
- Does not affect my ability to remain on the staffing platform
(only my biometric data is removed)
- Triggers permanent destruction of all biometric data within
30 days, per the destruction runbook
- Is recorded as an append-only audit row in my per-subject
audit log, providing me with tamper-evident proof of withdrawal
if I subsequently exercise my BIPA right of action
⚖ COUNSEL — confirm 30 days is the right destruction SLA. Some
deployments use 7 or 14 days. The runbook (Gate 5) currently
references this template's number, so changing it here updates
both.
---
## 3. Contact for withdrawal / questions
⚖ COUNSEL — supply the candidate-facing contact channel for
biometric-consent withdrawal. Examples: a dedicated email
(`biometric-consent@<deployment-domain>`), a postal address, a
named operator. The contact must be functional from day one of
deployment.
---
## 4. Consent acknowledgment
By signing below (electronically or on paper), I acknowledge that:
1. I have read and understood the disclosures in §1-3 above
2. I am providing this consent voluntarily and free of coercion
3. I have received a copy of this consent template (or have been
provided a means to retrieve a copy at any time)
| Field | Value |
|---|---|
| Candidate name | _______________________________ |
| Date | __________ |
| Signature | _______________________________ |
| Consent template version | v1 (SHA-256: _generated at deployment time_) |
---
## 5. Operational integration
The structured fields the consent UI must capture and post to
identityd:
```json
{
"candidate_id": "<token>",
"consent_version_hash": "<sha256 of this file at deployment>",
"consent_given_at": "<ISO-8601 timestamp>",
"consent_collection_method": "<electronic_signature|paper|click_acceptance>",
"consent_collection_evidence_path": "<path to signed artifact, if applicable>"
}
```
These fields write to `SubjectManifest.consent.biometric.status='given'`
and the corresponding `SubjectAuditRow` (see
`crates/catalogd/src/subject_audit.rs`).
---
## 6. Versioning
This consent template is version v1. Per Gate 1's versioning rules,
any change to the binding disclosure language requires a new version,
and existing subjects retain their original consent_version reference
unless they re-consent under the new version.
⚖ COUNSEL — confirm whether existing consent under v1 carries forward
when the schedule is updated, or whether re-consent is required.
This affects the deployment workflow.
---
## 7. Authority
| Role | Name | Signature | Date |
|---|---|---|---|
| Operator | J | _______________ | _____ |
| Outside counsel | _____________ | _______________ | _____ |