> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mareaalcalina.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ARCO procedures (LFPDPPP)

> Mexican data-rights compliance: Acceso, Rectificación, Cancelación, Oposición. Endpoints and retention windows.

# ARCO procedures

Marea Alcalina is a Mexican corporation and is subject to **LFPDPPP** (Articles 16–18), the Mexican federal personal-data-protection statute. Every account holder has four enumerated rights — collectively **ARCO**:

| Right             | Spanish       | What the user can do                         |
| ----------------- | ------------- | -------------------------------------------- |
| **A**cceso        | Acceso        | Access a copy of their personal data         |
| **R**ectificación | Rectificación | Correct inaccurate or incomplete data        |
| **C**ancelación   | Cancelación   | Delete their account and all associated data |
| **O**posición     | Oposición     | Object to specific processing of their data  |

Brazilian residents have a parallel set of rights under LGPD (Lei Geral de Proteção de Dados). The technical surfaces below honor both.

## How users exercise ARCO

### Access + Rectification (online, self-serve)

The dashboard at [mareaalcalina.com/dashboard](https://mareaalcalina.com/dashboard) exposes:

* Account email, displayName, language, currency, country, plan, verification status, `tosAcceptedAt`.
* Every storefront the account owns + its products.
* Each user key issued for the account (label, prefix, scopes, last used).

API equivalents:

| Endpoint                | Key                          | Returns                                               |
| ----------------------- | ---------------------------- | ----------------------------------------------------- |
| `GET /v1/me`            | `mk_user_*` / `mk_dev_*`     | Identity + plan + rate-limit window + dashboard links |
| `GET /v1/users/:userId` | `mk_dev_*` (developer scope) | The full user DTO for users the dev key bootstrapped  |
| `GET /v1/users`         | `mk_dev_*` (developer scope) | Paginated list of users the dev key bootstrapped      |

Storefront and product contents are exposed through the dashboard for Acceso today; the API v1 catalog surface is currently write-only (`POST` / `PATCH`), so for an LFPDPPP Acceso request that needs storefront contents, direct the user to the dashboard above. Rectification of catalog data goes through `PATCH /v1/storefronts/:storefrontId` (deep-merge, see [Storefronts](/concepts/storefronts)).

### Cancellation (hard delete)

Three paths trigger an LFPDPPP-compliant hard delete:

| Path                                                                         | Triggered by              | Idempotent |
| ---------------------------------------------------------------------------- | ------------------------- | ---------- |
| Dashboard "Delete account" button                                            | User (interactive)        | Yes        |
| `DELETE /public/v1/bootstrap/:previewToken` (or two-step `GET` confirm flow) | Bootstrap-email recipient | Yes        |
| Scheduled cleanup (`30d_unverified` or `90d_no_tos`)                         | System                    | Yes        |

The public bootstrap-cancel endpoint is unauthenticated by API key — the **preview token is the auth** (256-bit random, 24h TTL, single-use). The link is embedded in every bootstrap verification email so a user who didn't ask for an account can self-cancel without ever logging in.

Hard delete removes, in this order:

1. **API keys** — every `apiKeys` doc where `ownerUid == :uid` (batched, 500-per-batch).
2. **Verification codes** — `apiVerificationCodes/{email}`.
3. **Preview tokens** — every `apiPreviewTokens` doc for this user.
4. **Storefronts + products** — `users/{uid}/menus/**` recursive delete.
5. **User document + subcollections** — `users/{uid}` recursive delete.
6. **Audit trail** — one append to `tosAcceptanceLog` recording reason + summary BEFORE the Auth delete.
7. **Firebase Auth user** — `auth().deleteUser(uid)`. Frees the email for re-signup.
8. **Webhook fan-out** — `user.cancelled` event (see [Webhooks](/concepts/webhooks)) with one of the locked `reason` values.

`reason` enum in the `user.cancelled` webhook:

| Value                 | Triggered by                                                     |
| --------------------- | ---------------------------------------------------------------- |
| `user_clicked_cancel` | Public bootstrap-cancel endpoint                                 |
| `squatting_defense`   | Email squatting defense (PRD-4)                                  |
| `30d_unverified`      | Scheduled cleanup — never verified within 30 days                |
| `90d_no_tos`          | Scheduled cleanup — verified but ToS not accepted within 90 days |
| `key_revoked`         | All other administrative or revocation-cascading deletes         |

### Opposition

To object to a specific processing activity (marketing, analytics, etc.) without cancelling the account, users may write to the contact channel below. Marea applies the change within the LFPDPPP-prescribed response window (20 business days from a verifiable request).

## Retention

* An **active** account is retained while it has a paid plan, has not invoked Cancelación, and has accepted ToS (or is within the 90-day window for agent-bootstrapped accounts).
* A **hard-deleted** account is removed from Firestore + Firebase Auth within the same job invocation. Orphan Cloud Logging entries decay per Google Cloud's standard retention (default 30 days).
* A **revoked API key** stops authenticating within \~60 seconds end-to-end and is retained server-side for audit purposes only (the `keyHash` is kept; the raw key was never stored).

## Contact channel

LFPDPPP / LGPD requests not satisfied by the self-serve paths above should be sent to the contact email on the dashboard footer. Marea's response SLA matches LFPDPPP statutory timelines (20 business days; 15 days for follow-ups).

## What an agent should know

* **Never** create an account on behalf of a user who has not authorized it. The cancel hatch protects misuse, but the user-rights regime treats unauthorized creation as a violation by the creating party.
* If the agent receives `user.cancelled` (any reason) for a user it bootstrapped, the agent must **stop** all downstream automation for that user and delete any local cached state.
* The agent **cannot** accept the ToS on the user's behalf. See [ToS jurisdiction](/concepts/tos-jurisdiction) for the 451 flow.

## Verification in code

* `src/api/public/bootstrap.cancel.ts` — public unauthenticated cancellation endpoint (preview-token auth).
* `src/api/services/account-delete.service.ts` — `hardDeleteUserAccount` ordering + audit-log write.
* `src/api/scheduled/CleanupUnverifiedAccounts.ts` — 30d / 90d sweep policy.
* `src/api/services/webhooks.service.ts` — `user.cancelled` event + `CancelReason` enum.
