Data Processing Agreement (DPA)
This Data Processing Agreement ("DPA") forms an integral part of the IQShield Terms of Service ("Main Agreement") and governs the processing of personal data by IQShield on behalf of the Client, in accordance with Art. 28 of Regulation (EU) 2016/679 ("GDPR").
1. Parties
- Data Controller: The Client of the IQShield service, as defined in the Main Agreement ("Controller")
- Data Processor: IQGroup Adam Buhl, NIP: 9910389442, ul. Luboszycka 36/1, 45-128 Opole, Poland ("Processor", "IQShield")
2. Subject and scope of processing
2.1. IQShield processes personal data of End Users solely for the purpose of providing the bot protection (CAPTCHA) service on the Controller's Protected Sites.
2.2. The processing includes:
| Element | Description |
|---|---|
| Purpose of processing | Verifying whether an interaction with the Protected Site originates from a human, not a bot |
| Nature of processing | Collection, storage (short-term), analysis, deletion |
| Categories of data subjects | End Users — visitors to the Controller's Protected Sites |
| Types of data | See section 3 |
| Duration | For the term of the Main Agreement |
| Location | European Union (Germany / Finland) |
3. Types of personal data processed
| Data | Classification | Retention period | Format |
|---|---|---|---|
| IP address | Personal data | Redis: max 60s (challenge) / 300s (token); PostgreSQL: 90 days | INET (PostgreSQL), text (Redis) |
| User-Agent | Pseudonymized | 90 days (verification_log) | Text |
| Device type | Anonymized (category) | 90 days | Text (desktop/mobile/tablet) |
| Behavioral signals | Pseudonymized / anonymized | 0 seconds — processed exclusively in RAM, never stored | — |
| Score (0.0–1.0) | Non-personal | 90 days | Floating-point number |
| Solve time (ms) | Non-personal | 90 days | Integer |
| Rate limit counters | Personal data (IP-linked) | 60 seconds (Redis TTL) | Counter |
Special categories of data (Art. 9 GDPR) are NOT processed.
4. Processor obligations
IQShield as Data Processor commits to:
4.1. Compliance with instructions
- Processing personal data only on documented instructions from the Controller (Main Agreement + this DPA)
- Promptly informing the Controller if, in its opinion, an instruction violates the GDPR or other data protection legislation
4.2. Confidentiality
Ensuring that persons authorized to process personal data have committed to confidentiality or are under a statutory obligation of confidentiality.
4.3. Technical and organizational measures
IQShield implements appropriate technical and organizational measures (Art. 32 GDPR):
| Measure | Description |
|---|---|
| Encryption in transit | TLS 1.2+ on all connections (API, Dashboard, CDN) |
| Encryption at rest | Encrypted disk volumes (PostgreSQL, Redis) |
| Access control | API key authentication (Site Key + Secret Key), RBAC in Dashboard |
| Data minimization | Behavioral signals processed in RAM only; only the score is stored to database |
| Pseudonymization | Tokens hashed with HMAC-SHA256; IP data not linked to identification data |
| System resilience | Redis with TTL (automatic expiration), PostgreSQL with automatic retention |
| Monitoring | Audit log of administrative operations, health checks |
| Updates | Regular security patches for systems and dependencies |
| Rate limiting | Per-IP and per-sitekey, abuse protection |
| Data isolation | Each Client's (site) data is isolated by site_id key |
4.4. Sub-processors
IQShield uses the following approved sub-processors:
| Sub-processor | Role | Location | Data processed |
|---|---|---|---|
| Hetzner Online GmbH | Server infrastructure (VM, storage) | Germany / Finland (EU) | All data within the Service |
| Supabase Inc. | Client account authentication | EU (Frankfurt) | Client email + password hash (NOT End User data) |
| Stripe Inc. / Paddle | Payments | EU + US (SCCs) | Client payment data (NOT End User data) |
- IQShield notifies the Controller of the intention to add or change a sub-processor with 30 days' advance notice via email
- The Controller has the right to raise a reasoned objection within 14 days of notification
- In case of objection, the parties will seek a resolution in good faith; if no agreement is reached, the Controller may terminate the Main Agreement
- IQShield ensures that sub-processors are bound by obligations no less restrictive than this DPA
4.5. Assistance to the Controller
IQShield assists the Controller with:
- (a) Fulfilling data subject rights (Art. 15-22 GDPR) — to the extent technically feasible
- (b) Ensuring security of processing (Art. 32)
- (c) Breach notification (Art. 33-34)
- (d) Data protection impact assessments (DPIA, Art. 35-36) — upon request
4.6. Data breach notification
- IQShield notifies the Controller of a personal data breach without undue delay, no later than 48 hours after becoming aware of the breach
- The notification includes: the nature of the breach, categories and approximate number of affected individuals, likely consequences, and measures taken/proposed to address the breach
- IQShield cooperates with the Controller in communicating with the supervisory authority and affected data subjects
4.7. Data deletion
Upon termination of the Main Agreement, IQShield:
- Deletes End User data associated with the Controller's sites within 30 days
- Redis data expires automatically (TTL)
- Verification_log data for the Controller's site_id is deleted from PostgreSQL
- Client billing data is retained for the period required by law (5 years — tax obligation)
Upon request, IQShield provides written confirmation of deletion.
5. Audit rights
5.1. IQShield makes available to the Controller upon request:
- (a) Information necessary to demonstrate compliance with Art. 28 GDPR obligations
- (b) Results of security audits or certifications (if available)
5.2. The Controller (or an authorized auditor) may conduct an audit once per year, upon 30 days' prior notice, at the Controller's expense, in a manner that does not disrupt the normal operation of the Service.
5.3. IQShield may propose that the audit be conducted by an independent auditor, whose report will be made available to the Controller.
6. Data transfer outside the EEA
6.1. IQShield does not transfer End User personal data outside the European Economic Area.
6.2. If engagement of a sub-processor outside the EEA becomes necessary, IQShield will:
- (a) Inform the Controller with 30 days' advance notice
- (b) Ensure appropriate safeguards (SCCs, adequacy decision)
- (c) Allow the Controller to object (see 4.4)
7. Liability
7.1. IQShield's liability under this DPA is subject to the limitations set out in the Main Agreement (Terms of Service, section 8).
7.2. IQShield is not liable for unlawful data processing by the Controller on their Protected Sites.
8. Duration
8.1. This DPA is effective for the entire duration of the Main Agreement.
8.2. Provisions regarding data deletion (4.7), confidentiality (4.2), and audit (5) survive termination of this DPA.
9. Final provisions
9.1. This DPA is governed by Polish law.
9.2. In case of conflict between this DPA and the Main Agreement, this DPA shall prevail with respect to data protection matters.
9.3. If any provision of this DPA is found to be invalid, the remaining provisions shall remain in force.
Annex A: Technical description of processing
Data flow (challenge → verify)
In-memory data (RAM) — never written to storage
mouse_entropy(float) — Shannon entropy of mouse movementsmouse_moves(int) — movement countkey_presses(int) — keystroke count (max 200)scroll_events(int) — scroll event countscroll_depth(int) — max scrollYfocus_changes(int) — visibility change countenv_fingerprint(string) — "lang|cores|platform|WxH|depth|tz"automation_signals(string) — automation detection flagshoneypot_filled(bool) — whether honeypot was filled
Persistently stored data (PostgreSQL, 90-day retention)
site_id(UUID) — Protected Site identifier (foreign key)token_id(text) — token hash (not the token itself)ip(INET) — End User IP addressuser_agent(text) — User-Agent headerdevice_type(text) — device categoryscore(real) — scoring result 0.0–1.0passed(boolean) — whether verification passedsolve_time_ms(integer) — solve time in millisecondscreated_at(timestamptz) — timestamp