Data Protection Document

Who controls what, on what basis, shared with whom, and across which borders — the record LGPD Art. 37 and GDPR Art. 30 require.

Data Protection Document — Heimdall API

1. Purpose

This is the record of processing activities LGPD Art. 37 and GDPR Art. 30 require, together with the two things that record depends on and that nothing else in this repository states: who controls the data, and where it goes.

It is kept here rather than in a filing cabinet because the schema is the source of truth and the schema changes. Keeping the record next to the requirements means it is reviewed in the same pull request as the migration that outdates it.

Retention periods are not repeated here. They live in the Data Retention Schedule , which Art. 30(1)(f) is satisfied by reference to.

2. Controller and Encarregado

ControllerArtur Rios
Contactarturdev@duck.com
Encarregado / DPOArtur Rios — arturdev@duck.com
Hosting regionBrazil

LGPD Art. 41 §1 requires the Encarregado’s identity and contact to be publicly disclosed. That is what §2 of the Privacy Notice does, and this row is its source.

The controller and the Encarregado are the same person. That is permitted, and for a project of this size it is the honest arrangement rather than an invented separation — but it is worth naming the consequence: there is no independent check on the controller’s own decisions. Where the project takes on a client whose scale makes that unacceptable, the Encarregado should be somebody else.

On small processing agents. ANPD Resolution CD/ANPD nº 2/2022 gives agentes de tratamento de pequeno porte a simplified regime — notably, appointing an Encarregado is optional provided a communication channel is published. This project appoints one anyway, because the channel has to exist either way and naming a person is clearer than naming an inbox. Whether the project qualifies as a small processing agent is a determination for the controller, and it does not change anything in this document.

3. Controller and processor, per scope

Heimdall is multi-tenant. Each Scope belongs to a different client system, and that client decides why its users’ data is processed. The allocation follows from that and has to be stated, because almost every downstream obligation depends on which side of it a given row falls.

DataRoleWhy
Persons and Google Users within a tenant scopeHeimdall is processor; the tenant organisation is controllerThe tenant decides the purpose — its own users, its own service. Heimdall stores and authenticates them on the tenant’s instructions
System Admin accountsHeimdall is controllerThey exist to operate Heimdall itself; no tenant determines their purpose
Audit trail (AUDIT_LOG)Heimdall is controllerKept for Heimdall’s own accountability under LGPD Art. 37 and GDPR Art. 5(2). A processor may hold records it needs to demonstrate its own compliance, and this is one
Application logs, security telemetryHeimdall is controllerSame reasoning: operating and defending the service is Heimdall’s own purpose, not a tenant’s instruction

Two consequences that are easy to miss:

  • A data subject request from a tenant’s user reaches a processor, not their controller. Heimdall answers it under UC-41/UC-42 where it can, and the Data Processing Agreement sets out when and how it must instead be routed to the tenant.
  • Heimdall must notify the tenant of a breach affecting their scope, without undue delay (GDPR Art. 33(2), LGPD Art. 48). That obligation is owed to the tenant, not the public.

4. Categories of data subject

CategoryWhere
Persons — User, ScopeAdmin, SystemAdminPERSON
Google-authenticated usersGOOGLE_USER

APPLICATION rows are out of scope: an application is a non-human identity representing another system. Its OwnerId names a person, but the row describes the system.

APPLICATION_CREDENTIAL rows (UC-53) are out of scope for the same reason. Each holds an application reference, the SHA-256 of a random secret, and four instants (issued, expiring, revoked, last used). None of them relates to a person, and the audit entries of credential operations name the acting administrator as every audit entry does (§5.1 AUDIT_LOG).

CategoryFieldsPurposeLGPD basisGDPR basis
IdentityName, EmailIdentify the account and address itArt. 7 V (execução de contrato)Art. 6(1)(b) contract
Authentication materialPasswordHash, Salt, SecurityStamp, TwoFactorAuth.TotpSecretEncrypted, recovery code hashesVerify that the account holder is presentArt. 7 V, Art. 46 (segurança)Art. 6(1)(b), Art. 32
Third-party identifiersGoogleUser.GoogleId, ProfilePictureUrlResolve a Google sign-in to a stored identityArt. 7 VArt. 6(1)(b)
Behavioural / securityFailedLoginAttempts, LockedOutUntil, the second-factor and re-authentication budgets, AUDIT_LOGDefend accounts against brute force; demonstrate what the system didArt. 7 IX (legítimo interesse), Art. 37Art. 6(1)(f) legitimate interests, Art. 5(2)
Deletion and erasure stateDeletedAt, DeletionKind, AnonymisedAt, ErasureRequestedAt, ErasureDueAt, ErasureBlockedReasonHonour erasure within the statutory deadline and show that it was honouredArt. 7 II (obrigação legal)Art. 6(1)(c) legal obligation
NetworkClient IP address: the rate limiter’s partition key (in memory), and every request’s entry in the application logs (12 months)Bound anonymous request rates; detect and investigate attacks on accountsArt. 7 IX, Art. 46Art. 6(1)(f), Art. 32
DeliveryRecipient address passed to MailgunSend verification, reset and second-factor emails, and the notice of an email change to the previous address (FR-PE-15)Art. 7 VArt. 6(1)(b)

Consent is not a basis anywhere in this table, and that is deliberate. Every processing operation here is necessary to run an identity service the account holder is a party to, or is required of the controller by law. Consent would be the wrong basis for all of it: it is withdrawable, and an identity provider that stopped verifying passwords on withdrawal would simply be broken.

It is also not selectable, not merely unused. A scope that declared consent would be recording a basis this system cannot honour — GDPR Art. 7(3) requires withdrawal to be as easy as giving it, and there is no withdrawal path. The validators refuse the value and the recorder refuses it again on the way out, because a guard in one direction only is one migration from being bypassed.

The basis is recorded per identity at creation, with the privacy notice version then in force (NFR-23). The version is stored rather than looked up later: what a person was told is a fact about a moment, and reading the current notice would answer a different question. A scope may declare the basis for identities within it, since the tenant is usually their controller (§3); where it declares none, contract performance applies.

Identities created before NFR-23 read Unrecorded. Contract performance almost certainly applied to all of them, and the migration deliberately did not write it: asserting in this record something nobody checked for those rows would demonstrate that a migration ran, not that a basis applied. They are visibly a thing to fix rather than silently indistinguishable from a row recorded properly.

No special categories of personal data (GDPR Art. 9, LGPD Art. 5 II) are processed. There is no automated decision-making producing legal effects (GDPR Art. 22, LGPD Art. 20).

5.1 Every column, and why it is held

§5 groups the data by category. This is the same data at the granularity a minimisation review needs (GDPR Art. 5(1)(c) and Art. 25, LGPD Art. 6 III): one row per column that holds personal data, each with the purpose that justifies holding it. A column with no purpose is a column to remove.

PERSON

ColumnPurpose
PublicIdThe identifier every other table and every token refers to. Random, so it discloses nothing by itself
NameAddressing the person in email, and downstream profile provisioning by client systems
EmailThe address the account is reached at, and the identifier a person signs in with
PasswordHash, SaltVerifying the person is present. Never reversible to the password
IsDeletedSuspending an identity without destroying it
EmailVerifiedWhether the address has been proven reachable (FR-EV-01)
FailedLoginAttempts, LockedOutUntilBounding credential guessing per account (FR-AU-09)
FailedSecondFactorAttempts, SecondFactorLockedOutUntil, SecondFactorLockoutsBounding second-factor guessing at sign-in per account, across challenges (FR-AU-12). Cleared by a successful second factor and by anonymisation (NFR-20)
FailedReauthenticationAttempts, ReauthenticationWindowStartedAt, ReauthenticationPausedUntilBounding password and code guessing under a bearer token per account (FR-AU-13). Cleared by a successful re-authentication and by anonymisation (NFR-20)
AccountEmailsSent, AccountEmailWindowEndsAt, AccountEmailLastSentAtBounding the account emails the person’s own requests can have sent — a verification link asked for again, a two-factor setup code, the notice an own email change sends to the previous address — to one per cooldown and five per day-long window (FR-PE-16), so an account cannot be used to flood an address. Returned in the data export; cleared by anonymisation (NFR-20)
SecurityStampRevoking the person’s tokens when a credential changes (FR-AU-11). A random value with no meaning of its own, replaced on each change
RoleId, ScopeIdAuthorisation, and the per-scope uniqueness index FR-PE-09 needs
CreatedAt, UpdatedAtOrdinary record keeping; UpdatedAt is why DeletedAt had to exist separately
DeletedAt, DeletionKind, AnonymisedAtMeasuring and enforcing the retention window (NFR-20)
ErasureRequestedAt, ErasureDueAt, ErasureBlockedReasonHonouring an erasure request within its deadline, and showing that it was honoured (UC-42, UC-43)
LegalBasis, PrivacyNoticeVersion, BasisRecordedAtDemonstrating the lawful basis and what the person was told when the account was created (NFR-23). Not data about the person so much as about the processing of them, and held for the same accountability duty that requires this document
ProcessingRestrictedAt, RestrictionGround, RestrictionLiftNotifiedAtHonouring a restriction of processing and evidencing that Art. 18(3)’s notification happened before it was lifted (NFR-24)

GOOGLE_USER

ColumnPurpose
PublicId, ScopeId, IsDeleted, CreatedAt, UpdatedAtAs above
GoogleIdGoogle’s sub. The only stable way to resolve a returning sign-in to a stored identity (FR-GO-08)
Name, Email, EmailVerifiedAs on PERSON
ProfilePictureUrlDownstream profile provisioning — see the decision below
DeletedAt, DeletionKind, AnonymisedAt, ErasureRequestedAt, ErasureDueAt, ErasureBlockedReason, LegalBasis, PrivacyNoticeVersion, BasisRecordedAt, ProcessingRestrictedAt, RestrictionGround, RestrictionLiftNotifiedAtAs above

AUDIT_LOG

ColumnPurpose
ActorPersonId, ActorRoleAttributing an action, for as long as NFR-21 permits and no longer
TargetIdWhat the action was taken on. When that is a person or Google User — their own account for a self-service command, or the person an administrator acted on — the entry is personal data about them whoever acted, so NFR-21 clears it on the same schedule as the actor: past the attribution period, or as soon as that identity is anonymised (#184). Any other target (a scope, an application, a credential, a permission) names no person and is kept. A person target whose row was hard-deleted (UC-05, UC-10, UC-29) is cleared too, on the next pass and at any age: the id still names the person to anything holding a copy of the old row, so it stays personal data, and the hard delete tombstones it in ERASED_SUBJECT before the row goes so the pass and the trigger can tell it was a person’s (#195). An id that resolves to nobody and was never tombstoned — a hard-deleted scope’s, or a person’s removed before tombstones existed — is kept
Action, Succeeded, FailureReason, CreatedAt, PublicIdWhat happened. Not personal data once the attribution and any person target are cleared

Readable through the API by System Admins (UC-48). GET /api/audit-log shows each entry as stored: an attribution or person target already cleared reads as null and is never reconstructed, whether by a join to PERSON or from neighbouring entries. The endpoint widens who can read the trail — from whoever can query the database to System Admins — without widening what it says about anyone. No column was added, so this table is unchanged.

This table is why NFR-23’s columns are here. They were added after the table existed, and PersonalDataPurposeTests failed the build until each was given a purpose — which is the control working rather than a formality. SCOPE.DefaultLegalBasis and SCOPE.PrivacyNoticeUri are absent deliberately: a scope is an organisation, not a person, so neither is personal data.

ERASED_SUBJECT

ColumnPurpose
PublicId, Kind, CreatedAtA short-lived processing record of a hard delete (#195): the removed person’s or Google User’s id, which of the two it was, and when. Held only so NFR-21 can clear the audit targets that still name the id — the hard delete’s own entry among them — once no row is left to say the id was a person’s. Removed by the first run of the same pass after its day of grace, once no entry names it. Nothing else about the person is kept, it is never read through the API, and the database accepts a row only for a person or Google User that exists when it is written (#195, R1)

PENDING_REGISTRATION

ColumnPurpose
PublicIdThe administrative reference a scope’s owners list and discard a registration by (UC-49, UC-50). Random, so it discloses nothing by itself; the registrant never sees it
ScopeIdThe scope the registrant asked to join — and so whose owners may see and discard the registration
Name, EmailWhat the account will be created with once the address is confirmed; the address is also where the confirmation link goes
PasswordHash, SaltThe password chosen at sign-up, so the account can be created with it and confirmation can require it (FR-SR-09). Never reversible to the password
TokenHashRecognising the mailed link without storing it (Threat Model TH-14)
ExpiresAt, CreatedAtBounding how long the link works, and when the row is purged (Data Retention Schedule)
FailedAttemptsBounding guesses at the sign-up password through a leaked link (FR-SR-09, NFR-27)

A scope’s owners and System Admins can read the id, name, address, creation and expiry times, the remaining guesses and whether it has expired through the API (UC-49) — the same name and address they would see in the scope’s user list once the registration is confirmed. The hash, salt and token hash are never returned.

ATTEMPT_NOTICE_BUDGET

ColumnPurpose
AddressHashWhich address a registration-attempt notice went to, so the address gets at most three a day however many scopes or source addresses the attempts come from (FR-SR-14). A SHA-256 digest of the trimmed, lower-cased address, never the address itself — pseudonymisation rather than anonymisation, since whoever already suspects an address can hash it and find the row
NoticesSent, WindowEndsAtHow many notices went out in the current one-day window and when it ends; the first notice after it ends starts a new one. Purged with the single-use tokens once the window has ended and the grace period passed (Data Retention Schedule)

The row is written when a notice is sent, which is to say when someone registered with an address that already holds an account; it records that much about the holder and nothing else. It is never read through the API.

It is linked to no person or Google User — the digest is of an address, which several accounts in different scopes may share — so erasure, anonymisation and a hard delete do not reach it, and the data export (UC-41) does not include it: there is no account to attach it to, and finding it would mean hashing the subject’s address to look it up, which is processing the row exists to avoid. What bounds it instead is its retention: it lasts at most the one-day window plus the grace period, and is then purged whether or not anyone asked.

Two decisions this review settled

ProfilePictureUrl stays, and it is the weakest case here. The issue that prompted this review proposed dropping it unless a consumer could be identified. One can: the same downstream profile-provisioning purpose that puts DisplayName in the auth token. A client system rendering a signed-in user wants a name and an avatar, and serving both from the identity provider is why the identity provider holds them.

It is recorded as the weakest case because the reasoning is thinner than for any other column. It is a URL to a photograph of a person, held for a convenience a client system could satisfy by asking Google itself, and required by FR-GO-05 rather than by anything the API does with it. If no client system reads it, it should be dropped — that is a question about deployments rather than about code, and it belongs to the controller. Removing it would change FR-GO-05 and break the two Google User read endpoints’ contract, which is why this review does not do it unilaterally.

The display name in the auth token is confirmed, with its consequence stated. A JWT travels further than a response body: client systems store it, put it in headers, and log it. Putting a name in one spreads that name into places this system does not control and cannot clean up. The purpose — letting a client provision a profile without a second call — is real, and the alternative of a profile endpoint would mean every client making an extra request on every sign-in. The decision stands; the consequence is recorded so that a future proposal to add anything else to the token is weighed against the same test.

6. Recipients

RecipientWhat reaches themWhy
Mailgun (Sinch)Recipient email address, message bodyDelivering verification, password reset and second-factor emails
Tenant scope organisationsThe identities within their own scope, and the self-registrations awaiting confirmation in it (UC-49: name, address, timestamps, guesses left)They are the controller for those; see §3
Hosting providerEverything, at restRunning the database and the API

The current sub-processor list is maintained in the Data Processing Agreement §7, which is also where the notification commitment for changing it lives.

6.1 Google is a source, not a recipient

An earlier version of this document listed Google as a recipient. That was wrong, and the correction matters because it removes an international transfer that was recorded as needing a mechanism.

GoogleIdTokenVerifier calls GoogleJsonWebSignature.ValidateAsync, which validates the token offline: it verifies the signature against Google’s published certificates, which the library caches and refreshes hourly, and checks the issuer, audience and expiry locally. The token is never sent to Google. The only outbound request is for Google’s public certificates, which carry no personal data.

The direction of travel is the opposite of what a recipient means. Google issues the token to the person’s browser, which passes it to a client system, which presents it here — so Google is where GoogleId, Email, Name and ProfilePictureUrl come from, and GDPR Art. 14 and LGPD Art. 9 make that something the data subject is told. It is disclosed in the Privacy Notice and in every UC-41 export’s sources.

The person’s own sign-in at Google is a separate matter, between them and Google under Google’s own terms. Enabling Google Sign-In for a scope makes it possible; it does not make Heimdall the party transferring anything.

7. International transfers

LegFromToGoverned byStatus
Email deliveryBrazilUnited States (Mailgun)LGPD Art. 33 IX + Art. 7 V✅ Ground established — §7.1
Email delivery, for EEA subjects if anyEEAUnited States (Mailgun)GDPR Art. 46(2)(c)✅ Sinch’s SCCs — §7.1
Direct sign-up by an EEA subject—Brazil (hosting)Not a Chapter V transfer✅ No exporter — §7.2
An EEA tenant’s usersEEA (tenant)Brazil (hosting)GDPR Art. 46(2)(c)✅ SCCs Module Two in the DPA — §7.2
Daily backupsBrazilEurope or an Art. 45-adequate country (MEGA)LGPD Art. 33 IX + Art. 7 V✅ Ground established — §7.3
Daily backups, for EEA subjects in the copyEEAEurope or an Art. 45-adequate country (MEGA)GDPR Art. 45✅ Adequacy — §7.3
Google ID token verification———Not a transfer — §6.1

Two outbound flows carry personal data: Mailgun and the backups. They are not comparable in scale. Mailgun receives one address at a time, at the moment a person asks for something; the backup is a full copy of every category in §3, every day. The Google leg was recorded here in error and is corrected in §6.1: the token is validated offline against cached public certificates and is never sent to Google.

7.1 Email delivery to Mailgun

LGPD: Art. 33 IX, resting on Art. 7 V. Art. 33 IX permits a transfer “quando necessário para atender as hipóteses previstas nos incisos II, V e VI do art. 7º desta Lei”, and Art. 7 V is “quando necessário para a execução de contrato ou de procedimentos preliminares relacionados a contrato do qual seja parte o titular, a pedido do titular dos dados”.

Every email this API sends is one of exactly three things: the verification that activates an account somebody asked for, the reset that restores access to it, or the second factor that lets them in. Each is necessary to perform the service the person is party to, and each is sent at their own request. The address reaching a mail provider is not incidental to that service — it is the service being performed.

This is the same basis §5 already records for the underlying processing, which is what makes it coherent rather than opportunistic: the transfer rests on the ground the processing itself rests on, not on a different one found for the occasion.

Why not Art. 33 II. The cláusulas-padrão contratuais route would require the ANPD’s own clauses (Resolution CD/ANPD nº 19 of 23 August 2024) in the Mailgun contract. Sinch’s published DPA is automatically incorporated and carries the EU Standard Contractual Clauses, with a Brazil annex that references the LGPD — but not the ANPD clauses. The ANPD may recognise foreign clauses as equivalent, and doing so requires a published Resolution of its Conselho Diretor; absent one for the EU SCCs, Art. 33 II would rest on an equivalence nobody has declared. The transition period for incorporating the ANPD clauses closed on 23 August 2025.

Art. 33 IX is a self-standing statutory ground that needs no counterparty agreement, which is why it is the one relied on.

GDPR, if it applies at all (§7.2). Sinch’s Data Processing Agreement forms part of the services agreement automatically, with no separate signature, and incorporates the EU Standard Contractual Clauses (Commission Decision 2021/914/EU, Modules 2 and 3) with Sinch as data importer. The EEA → US leg is therefore covered by Art. 46(2)(c) safeguards already in force.

Nothing needs to be signed. Neither ground requires negotiating or executing an agreement: Art. 33 IX is statutory, and Sinch’s SCCs are incorporated by their own terms.

The Mailgun region remains a configuration choice. Mailgun offers an EU region; moving to it would not remove the transfer, since the data still leaves Brazil. It would change which second jurisdiction is involved. Recorded next to MAILGUN_API_KEY in the operations guide so the choice is made deliberately rather than inherited.

Review trigger. If the ANPD publishes a Resolution recognising the EU SCCs as equivalent, Art. 33 II becomes available through Sinch’s existing DPA with nothing to sign, and is the stronger ground. Worth checking when this document is next reviewed.

7.2 GDPR applies — determined 10 September 2026

The controller has determined that the service is open to EEA data subjects. Nothing restricts access by geography once it is published, so GDPR is treated as applying under Art. 3(2). Recorded here with its date, and revisited if the service’s reach changes.

That settles the question this section was opened for. What follows is the consequence, and it is narrower than it first appears.

Hosting in Brazil is not, by itself, a restricted transfer

Brazil holds no adequacy decision, so the instinct is that storing EEA subjects’ data here needs Art. 46 safeguards. For the people who sign up directly, it does not.

EDPB Guidelines 05/2021 set three cumulative criteria for a Chapter V transfer: an exporter subject to the GDPR, disclosing to a separate importer, in a third country. The guidelines are explicit that “there will not be a transfer when the data are disclosed directly by the data subject to the recipient as there will be no exporter”. A person in the EEA creating an account here is sending their own data; they are not an exporter, and the first criterion fails.

So GDPR applies to that processing in full under Art. 3(2) — every right, every obligation in this document — but Chapter V does not engage, and no safeguard is required for the hosting itself.

A tenant established in the EEA is an exporter

Where a tenant organisation subject to the GDPR uses a scope for its own users, all three criteria are met: the tenant is the exporter and controller, Heimdall is the importer and processor, and the importer is in a third country. That is a restricted transfer and needs Art. 46 safeguards.

The safeguard belongs in the Data Processing Agreement , which is Heimdall’s own template rather than a third party’s, so it requires no negotiation with anybody: §7.1 of that agreement now incorporates the EU Standard Contractual Clauses, Module Two (controller to processor), with the tenant as exporter and Heimdall as importer. An EEA tenant executing the DPA receives the safeguard by doing so.

A transfer impact assessment remains the exporting tenant’s to make — it is an assessment of the importer’s jurisdiction from the exporter’s position, and the exporter is the only party who can make it. §7.2 of the DPA sets out what Heimdall supplies to support one.

Consequences elsewhere

  • The Brazil → United States email flow (§7.1) is unaffected: Art. 33 IX carries it under the LGPD, and Sinch’s own DPA carries the EU leg under Art. 46(2)(c).
  • The Incident Response Document §4 no longer needs its provisional instruction to assume GDPR applies. It does apply, and the shorter of the two notification clocks governs.

The risks this processing creates for the people in it, rated for them rather than for the system, are the Data Protection Impact Assessment .

7.3 Daily backups to MEGA

The backups are held by MEGA, encrypted on this side before MEGA receives them. The factual basis — which countries, what MEGA can and cannot see, and why the facility cannot be pinned — is in §0.1 of the Operations & Infrastructure Document . This section records the grounds.

This is the largest transfer the system performs, and it is worth stating plainly rather than letting it sit in a table row. Everything in §3 leaves the country daily: every name, every address, every audit entry, every hash. The email flow’s exposure is one address at the moment somebody asks for a reset. These are different in kind, and the ground had to be established with that in mind.

LGPD: Art. 33 IX, resting on Art. 7 V — the same construction §7.1 uses for Mailgun, and for the same reason. A backup is not a convenience separable from the service: an identity provider that cannot be restored is one that loses every account it holds on a single disk failure, and the contract the subject is party to is precisely that their identity will still exist tomorrow. Art. 7 V’s “necessário para a execução de contrato” covers the durability of the thing being executed, not only its moment-to-moment operation.

Why not Art. 33 I, despite the adequacy decisions. MEGA stores in Europe or in countries the European Commission has ruled adequate under GDPR Art. 45. That is a European finding and the LGPD does not import it. Art. 33 I requires a country recognised as adequate by the ANPD, and the ANPD has recognised none — the list does not exist yet. Relying on Art. 33 I here would mean citing one regulator’s decision to satisfy another’s statute.

Why not Art. 33 II. The same obstacle as §7.1, and a firmer one: MEGA’s terms are not negotiated per customer, so the ANPD’s standard contractual clauses could only enter by MEGA choosing to adopt them. Nothing suggests they have.

GDPR: Art. 45 adequacy. Where the copy contains EEA subjects’ data — from an EEA tenant, per §7.2 — the destination is either inside the EEA or a country covered by a subsisting adequacy decision. New Zealand’s is Commission Implementing Decision 2013/65/EU, which the Commission confirmed remains in force in its January 2024 review. Art. 45 transfers require no further authorisation, so nothing needs to be signed for this leg either.

And a supplementary measure that would carry it without adequacy. The backup is encrypted before it leaves and MEGA holds no key that decrypts it, which is EDPB Recommendations 01/2020 Use Case 1 almost exactly: encrypted storage in a third country, for backup, where the importer never needs the data in the clear and the keys stay with the exporter. This is recorded because it is what makes the analysis robust to the thing most likely to change — an adequacy decision being suspended or annulled, as one has been before. If that happened, the encryption is the argument that survives it, and the review trigger below exists to make somebody check.

Review trigger. If any adequacy decision MEGA relies on is suspended or annulled, the GDPR leg falls back on the encryption as its supplementary measure and needs re-documenting under Art. 46 — not re-engineering. If the ANPD publishes an adequacy list, Art. 33 I becomes available for whichever destinations appear on it, and is the stronger ground.

The residual exposure is the account password, not the jurisdiction. Both grounds above assume MEGA cannot read the copy, and that assumption rests entirely on the account credentials. It is recorded as an operational control in §0.1 of the Operations document rather than left implicit here, because it is the one thing in this section that can fail quietly.

8. Security measures

Not restated here. LGPD Art. 46 and GDPR Art. 32 are addressed by the controls the Threat Model documents and NFR-02, NFR-03, NFR-13, NFR-15, NFR-16 and NFR-17 require. What that model deliberately does not cover — encryption at rest, backups, and breach detection — is #106 and #105 .

9. Data subject rights

RightLGPDGDPRWhere
Confirmation and accessArt. 18 I–IIArt. 15✅ UC-41, self-service
PortabilityArt. 18 VArt. 20✅ UC-41 — structured JSON, machine-readable
CorrectionArt. 18 IIIArt. 16✅ UC-08, self-service
Erasure / eliminationArt. 18 VIArt. 17✅ UC-42, completed by NFR-20
Restriction of processingArt. 18 IVArt. 18✅ UC-44, self-service
Information about sharingArt. 18 VIIArt. 15(1)(c)✅ §6 of this document, and in every UC-41 export
ObjectionArt. 18 §Art. 21✅ UC-44 with the ObjectionPending ground, which restricts processing while the objection is weighed

Deadlines: LGPD Art. 19 §2 — 15 days for confirmation and access; GDPR Art. 12(3) — one month. The shorter one governs where both apply.

10. Reviewing this document

Reviewed when a migration adds or removes a column holding personal data; when a recipient or sub-processor changes; when the hosting region changes; when a transfer mechanism is executed or lapses; and when §7.2’s EEA determination is made or changes.

§5.1 is enforced rather than trusted. PersonalDataPurposeTests reflects over the entities that hold personal data and fails if a property is missing from the table above. A record of processing that silently falls behind the schema is worse than none, because it is relied on; this makes a new column arrive with a stated purpose or not arrive at all.