File size: 4,553 Bytes
a6a5d8e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# GDPR Article 17 — Right to Erasure Endpoint

**Flagship:** a11oy
**Endpoint:** `POST /api/a11oy/v2/erase`
**Doctrine v11 — 749 / 14 / 163 — replay hash c7c0ba17**
**Updated:** 2026-06-02

---

## Summary

Public flagships do not store end-user PII. All HF Spaces are unauthenticated and public.
This endpoint exists as the GDPR Article 17 minimum viable surface: it accepts an erasure
request, signs a receipt (whether or not any data exists to erase), and returns that signed
receipt to the caller.

---

## Request

```http
POST /api/a11oy/v2/erase
Content-Type: application/json

{
  "caller_id": "<string — your identifier, used only to label the receipt>",
  "confirmation": "DELETE-MY-DATA"
}
```

**Fields:**

| Field | Type | Required | Description |
|---|---|---|---|
| `caller_id` | string | yes | Caller-supplied identifier (not stored, used only in the receipt label) |
| `confirmation` | string | yes | Must be the literal string `DELETE-MY-DATA` |

---

## Response

```json
{
  "status": "acknowledged",
  "message": "Public flagships don't store user PII. Khipu chain receipts are auditable, not PII. Personal data deletion via rosie /api/rosie/v2/unay/erase (separate handler for operator session memory). Audit-trail receipt of this deletion request signed and returned.",
  "receipt": {
    "payload": {
      "type": "gdpr_erase_request",
      "flagship": "a11oy",
      "caller_id_label": "<caller_id from request>",
      "ts": "<ISO8601 timestamp>",
      "doctrine": {
        "declarations": 749,
        "axioms": 14,
        "sorries": 163,
        "replay_hash": "c7c0ba17"
      }
    },
    "signature": "<Wire D DSSE Ed25519 signature>",
    "prev_hash": "<Khipu chain prev_hash>"
  }
}
```

---

## What data is and is not held

| Data class | Held by a11oy? | Notes |
|---|---|---|
| PII from HF Space callers | **No** | HF Spaces are unauthenticated; no accounts, no cookies |
| Khipu chain receipts | Yes (audit trail) | Receipts are cryptographic audit records, not PII; deletion would break chain integrity |
| Operator session memory (rosie only) | rosie only | Route to `POST /api/rosie/v2/unay/erase` for operator session data |
| GitHub interaction data | GitHub (not us) | Contact GitHub directly for their data deletion |

---

## Implementation Reference

The endpoint handler (`serve.py`) must:

1. Validate `confirmation == "DELETE-MY-DATA"` — return 400 if not.
2. Build a receipt payload with `type: "gdpr_erase_request"`, `flagship`, `caller_id_label`, `ts`, and `doctrine` numbers.
3. Sign via `szl_dsse.sign(payload, WIRE_D_SIGNING_KEY)` — return 500 if signing fails.
4. Return 200 with `status: "acknowledged"` and the signed receipt.
5. **Do not log** `caller_id` beyond the signed receipt.
6. **Do not store** the request (the signed receipt itself is the audit trail).

```python
# Reference implementation (docs/reference; do not copy verbatim into serve.py without review)
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
import szl_dsse, datetime, os

router = APIRouter()

class EraseRequest(BaseModel):
    caller_id: str
    confirmation: str

@router.post("/api/a11oy/v2/erase")
async def gdpr_erase(body: EraseRequest):
    if body.confirmation != "DELETE-MY-DATA":
        raise HTTPException(400, "confirmation must be 'DELETE-MY-DATA'")
    payload = {
        "type": "gdpr_erase_request",
        "flagship": "a11oy",
        "caller_id_label": body.caller_id,
        "ts": datetime.datetime.utcnow().isoformat() + "Z",
        "doctrine": {"declarations": 749, "axioms": 14, "sorries": 163, "replay_hash": "c7c0ba17"},
    }
    key = os.environ.get("WIRE_D_SIGNING_KEY")
    if not key:
        raise HTTPException(500, "Signing key not configured")
    receipt = szl_dsse.sign(payload, key)
    return {
        "status": "acknowledged",
        "message": (
            "Public flagships don't store user PII; Khipu chain receipts are auditable not PII. "
            "Personal data deletion via rosie /api/rosie/v2/unay/erase (separate handler). "
            "Audit-trail receipt of deletion request signed."
        ),
        "receipt": receipt,
    }
```

---

## Routing to rosie

For operator session memory (if applicable), route the request to rosie:

```http
POST https://SZLHOLDINGS-rosie.hf.space/api/rosie/v2/unay/erase
Content-Type: application/json

{
  "caller_id": "<your identifier>",
  "confirmation": "DELETE-MY-DATA"
}
```

---

*Co-Authored-By: Perplexity Computer Agent*
*Doctrine v11 — 749/14/163 — c7c0ba17*