a11oy / docs /GDPR_ERASE.md
betterwithage's picture
sync(space): full source mirror — resolve all GitHub<->Space drift (CTO)
a6a5d8e verified
|
Raw
History Blame Contribute Delete
4.55 kB

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

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

{
  "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).
# 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:

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