# spun.ink — Data Processing Agreement (Art. 28 GDPR)

> Version 2026-08-25b · content hash: the SHA-256 of the served bytes, printed on the page itself at
> `spun.ink/legal/dpa` and reproducible from the raw markdown at `spun.ink/legal/dpa.md` ·
> applies to: every spun.ink account, on every plan (Free, Pro, Agency), anywhere in the world, in so
> far as City of Code GmbH processes personal data on the Customer's behalf · supersedes: version
> 2026-08-25, readable at `spun.ink/legal/dpa/2026-08-25`.
>
> **One change: our error tracker is now also told what our software logged.** Until now AppSignal
> received crash reports and timings. It now also receives the log lines our software writes at
> warning level and above — what failed, on which request, for which account and Site — because a
> crash report on its own does not say what led to it. What is *not* sent is unchanged and still
> switched off in our deployment: no request parameters, no session data, no Visitor IP address, no
> query strings. Annex 2.1 and Annex 3 name the new category and its retention: **log lines are kept
> at most 5 days**, against 60 days for a crash report.
>
> **Nothing about who processes your data changed**, and no new sub-processor was engaged — this is
> a wider category of data to a company already named in Annex 2. At the time of this version
> spun.ink still has no customer accounts, so no section 11.2 notice was due and none was sent. Any
> later widening is announced first, under section 20.2 or section 11.2 as the change requires.
>
> Effective 2026-08-25. English is the contract language.
> **Part of the spun.ink Terms of Service. Accepting the Terms accepts this document** — there is
> nothing separate to sign.
> Companion documents: **Terms of Service** (`/legal/terms`), **Privacy Notice** (`/legal/privacy`),
> **Legal notice** (`/legal/imprint`), **Acceptable Use Policy** (`/legal/acceptable-use`), **Right
> of withdrawal** (`/legal/withdrawal`).
> Previous versions: 2026-08-20, 2026-08-24, 2026-08-24b and 2026-08-25. Every version stays reachable
> at `spun.ink/legal/dpa/<version>`.

---

## In one minute — a plain-language summary

When you run a website on spun.ink, people who visit that website may give you personal data. They
fill in your contact form. You publish a page that names someone. You upload a photograph. **That
data is yours, not ours.** You decide what it is for; we only store it, serve it and hand it back to
you when your AI agent asks for it.

The GDPR calls you the **controller** and calls us the **processor**, and it requires a written
contract between us for exactly that situation. This document is that contract. It says what we
process and why, that we never use your visitors' data for our own purposes, who else touches it,
how we protect it, what we do when something goes wrong, what you have to do, and what happens to
the data when you leave.

Two things in here will surprise you, so they get their own sections and are not buried:

- **Section 7** — when your agent reads a form submission, the visitor's words go into your agent's
  AI context. That is your decision and your responsibility, and this agreement is where you
  instruct us to do it.
- **Section 6** — some things we do are *not* done for you: security logging, abuse handling and
  suspending a site that breaks the rules are our own decisions under the Terms, not your
  instructions.

**This summary is not the contract.** The numbered sections below are.

---

## 1. Who this is between

**The Processor**

```
City of Code GmbH
Adnet 436, 5421 Adnet, Austria
E-mail: support@spun.ink   ·   +43 664 8111838
Commercial register: FN 362676y · Firmenbuchgericht: Landesgericht Salzburg
VAT identification number: ATU66573656
Managing director (Geschäftsführer): DI Norbert Egger, BSc
```

spun.ink is a product and service of City of Code GmbH. In this document "**we**", "**us**" and
"**spun.ink**" mean City of Code GmbH.

**The Controller — you, the Customer.** You are the Customer as defined in section 1 of the **Terms
of Service** (`/legal/terms`): the natural person who instructs the Agent, or the legal entity that
person represents and warrants authority to bind. You are identified by the e-mail address on your
account and, where you have made a business declaration, by the name in that declaration. **Honest
status:** `get_account` today returns the account e-mail, plan and verification status, plan limits
and usage, and subscription status — there is no dedicated field yet for the name we use for you in
this agreement. Until one ships, write to `support@spun.ink` if you need us to confirm the name on
file.

**No data protection officer is required or appointed** on our side. Write to `support@spun.ink`.

## 2. How this agreement is concluded, and what it outranks

**2.1 You accept this agreement as part of the spun.ink Terms of Service for the plan you have
booked.** There is no second signature and no second click. Accepting the Terms accepts this
document, the **Privacy Notice**, the **Acceptable Use Policy** and the **Right of withdrawal**
instruction together.

**2.2 Acceptance is electronic, and it is recorded.** Art. 28(9) GDPR requires this contract to be
"in writing, including in electronic form". Against your account we record the version of the Terms
you accepted, the SHA-256 content hash of the exact bytes you were shown, the moment the acceptance
was declared at sign-up, and the moment you confirmed it yourself. Your Agent can read that record
back at any time — it is the `legal` block of `get_account`. The recorded version is what makes the
text you accepted producible years later: every version keeps answering at its own address,
`spun.ink/legal/dpa/<version>`. The binding act is the **Owner's
own click** on the button in the confirmation e-mail spun.ink sends after sign-up — not anything your
Agent declares. Where your Agent passes a terms version on `sign_up`, that is the Agent's attestation
that it showed you the Terms and got a yes; it is stored, and it does not by itself bind you.

**2.3 Precedence.** In so far as we act as your processor, **this agreement prevails over the Terms
of Service** where the two conflict. On everything else the Terms prevail. The **Right of
withdrawal** instruction prevails on withdrawal mechanics.

**2.4 No signature block.** There is none, deliberately. The electronic record described in 2.2 is
the form this contract takes.

**2.5 Two consolidations, so you are not left searching.** The sub-processor list and the catalogue
of technical and organisational measures are **Annex 1 and Annex 2 of this document**, not separate
pages. If you were sent looking for a "sub-processor page" or a "TOM page", this is where they live.

## 3. What we process for you, and why

**3.1 Subject matter.** Hosting and operating the website or websites in your account.

**3.2 Nature and purpose of the processing.** We do the following, and only the following, with the
personal data covered by this agreement:

- store the Content of your Site — pages, posts, templates, blocks, collections and records,
  navigation, settings, blogs and forms;
- render and serve those pages to Visitors on your Site's public addresses;
- receive Submissions from forms on your Site and store them for you;
- store uploaded assets and serve them over private storage with signed, expiring links;
- fetch an asset from a URL you or your Agent give us, and store it;
- build and maintain the search index that powers your Site's own search;
- keep revision snapshots of your Content and templates so you can restore them;
- keep backups so the service can be restored after a failure;
- return all of the above to you and to the Agent you connect, through the MCP tools of your
  account.

**3.3 Duration.** From the creation of your account until it is deleted. Deleting a Submission,
Content item or asset ends the processing of that item; deleting the account ends the processing of
everything (section 15).

**3.4 Where the processing happens.** In the European Union — Google Cloud region `europe-west1`
(Belgium), with the diagnostic data described in Annex 2.1 additionally held in the Netherlands by
our error-tracking provider. Section 11 and Annex 3 describe the transfers that nevertheless exist
and the safeguards for them. We do not claim that no data ever leaves the EU; that claim would be
false.

## 4. Categories of data subjects and of personal data

**4.1 Data subjects**

- Visitors to your Site.
- People who submit one of your forms.
- People described, named, quoted or depicted in your Content — in pages, posts, collection records,
  navigation labels, settings and uploaded assets.

**4.2 Personal data.** Whatever you and your Visitors put in. Forms on a spun.ink Site are free-form:
you define the fields, so the categories are yours to choose. In practice this means names, e-mail
addresses, telephone numbers, postal addresses, message text, and any file, image or document
uploaded to the Site.

**4.3 Special categories.** Because the fields are yours, a Submission or a page **may contain data
of the special categories in Art. 9 GDPR** (for example health, religious or philosophical beliefs,
trade-union membership, sex life or sexual orientation) or data relating to criminal convictions and
offences under Art. 10 GDPR. We neither require nor solicit such data. If your Site collects it, you
are responsible for the lawful basis, for the additional protections it needs, and for telling us so
that we can take it into account — see section 18.2.

**4.4 What we do *not* receive with a Submission.** A Submission stores the fields, the form name,
your account and site, and the time. **It stores no IP address and no user agent.** Our rate limiter
sees a Visitor's IP address in memory to decide whether to accept the request and never writes it to
the database.

## 5. Your instructions — the tools are the instructions

**5.1 The documented instructions** under Art. 28(3)(a) GDPR are, together and exhaustively:

1. this agreement and the **Terms of Service**;
2. every MCP tool call made with a bearer token or operator token of your account — creating,
   updating, publishing, unpublishing, reading, exporting or deleting anything;
3. the configuration you set through those tools — your Site's settings, templates, navigation,
   forms and plan.

That is what "the tools are the instructions" means. A tool call is a written instruction in
electronic form; we act on it and keep no separate instruction channel. `publish_content` is your
instruction to make a page publicly available. `delete_submission` is your instruction to erase that
Submission. `delete_account` is your instruction to erase everything (section 15).

**5.2 We process on your instructions only**, unless EU or Austrian law requires otherwise. Where
such a law requires us to process, we will tell you before we do, unless that law forbids us to tell
you on important grounds of public interest (Art. 28(3)(a) GDPR). Section 14 covers orders from
authorities.

**5.3 Additional instructions.** You may give us an instruction that the tools do not express, in
writing to `support@spun.ink`. We will confirm whether we can follow it. If following it would
require work beyond the service you have booked, we will say so before doing it, and — for business
Customers — may agree a reasonable charge first.

**5.4 We will warn you** if, in our opinion, an instruction of yours infringes the GDPR or other EU
or Austrian data protection law. We will tell you without delay and may suspend that instruction
until you confirm or withdraw it (Art. 28(3), final subparagraph).

## 6. What this agreement does **not** cover — the things we do for ourselves

Not everything City of Code does is done on your instruction, and pretending otherwise would
misdescribe both of us. **We act as controller in our own right**, under the **Terms of Service**
and the **Privacy Notice**, for:

- **your account data** — the account e-mail address, the account name, token digests, plan and
  subscription state, verification timestamps, and any feedback you send us;
- **billing** — handled by Stripe as an independent controller; billing records are our records, not
  yours (see 15.4);
- **security and operations logging**, rate limiting and abuse prevention across the platform;
- **handling reports of illegal content, applying the Acceptable Use Policy, and suspending or
  restricting a Site** — a suspension is our decision under the Terms, it is not an instruction from
  you, and it is not a breach of this agreement;
- **complying with orders from authorities and courts** addressed to us (section 14).

None of that is processing on your behalf, and none of it is governed by this agreement. It is
described in the **Privacy Notice** (`/legal/privacy`). We do not carry any of it out on your Visitors'
data for a purpose of our own beyond what is listed here.

## 7. Reading a Submission sends it to your own AI agent

**This clause is flagged because it will surprise you. Read it before you build a form.**

spun.ink has **no human admin interface for content**. The only way to read a Submission is for an
AI agent to call `get_submission` or `list_submissions` over MCP. **When it does, the Visitor's
submitted data is returned verbatim into that agent's context** — and from there into the model your
agent talks to.

- The Agent is **yours**. You choose the client, you connect it with your own credentials, and you
  choose the model vendor behind it.
- **spun.ink makes no model calls of its own.** We have no contract with any model vendor for your
  data, we send nothing to one, and no model vendor is a sub-processor under this agreement
  (Annex 2).
- **For that hop, you are the controller**, and the vendor of the model your Agent uses is **your**
  processor. You are responsible for having a contract with them, for the lawful basis, and for
  telling your Visitors — in your Site's own privacy notice — that submissions are read by an AI
  agent, if that is what you do.
- **Accepting this agreement is your documented instruction to return Submission data to the Agent
  that asks for it under a token of your account.** Without that instruction we could not answer the
  call at all.

If you do not want visitor data going into an AI context, do not read the Submissions with an agent
whose model vendor you have not cleared — and consider whether your form needs the field at all
(Art. 5(1)(c) GDPR).

## 8. No use for our own purposes

We do not use the personal data covered by this agreement for any purpose of our own. Specifically,
we do not use it to train or evaluate any model, we do not analyse it across accounts, we do not
profile Visitors, we do not sell it, and we do not enrich it. If we ever did, we would become the
controller for that processing under Art. 28(10) GDPR — so the rule is a design rule as much as a
contractual one.

## 9. Confidentiality

**9.1** Every person on our side who can access personal data covered by this agreement is bound to
confidentiality, and that duty survives the end of their engagement. In Austria, for our employees
and people in an employee-like relationship, this duty also follows directly from the
**Datengeheimnis** in § 6(1) DSG. For anyone outside that category — a contractor, for example — the
duty is contractual, not automatic (§ 6(2) DSG); see 9.2 for the honest status of those
undertakings.

**9.2 Honest status.** § 6(2) DSG requires the undertaking to be contractual where it does not
already follow from law. **Signed individual confidentiality undertakings are not yet on file** for
everyone with production access. Putting them on file is an open item, tracked as a pre-launch
governance task. Until then this section states a commitment we owe you, not a completed control —
and Annex 1 marks it as *planned*, not as done.

**9.3** Access to production data is limited to the people who need it to operate and support the
service, and is exercised through the platform's own tools and the cloud console, not through shared
accounts.

## 10. Security of processing (Art. 32 GDPR)

**10.1** We implement appropriate technical and organisational measures to ensure a level of
security appropriate to the risk. They are described in **Annex 1**.

**10.2** Annex 1 is honest about what is in place and what is planned. Where it says *planned*, the
measure is **not** in place today, and that half of the annex is **descriptive and
non-contractual** — it tells you our roadmap, it does not promise a date. Everything Annex 1 lists
as in place is a commitment.

**10.3** We may change a measure, provided the level of security does not drop below what Annex 1
describes. A change that lowers the level of protection follows the change procedure in section 20.

**10.4** Art. 30(2) GDPR requires us to keep a processor record. **Honest status:** it is not yet on
file — see Annex 1, section E.

## 11. Sub-processors (Art. 28(2) and (4) GDPR)

**11.1 General authorisation.** You give us general written authorisation to engage other processors
for the processing covered by this agreement. The current list is **Annex 2**.

**11.2 Notice and objection.** Before a new sub-processor starts processing your data, or before one
is replaced, we notify you **by e-mail to the account e-mail address**, and we update Annex 2. You
may object **within 10 days of the notice**, on substantiated data-protection grounds, by writing to
`support@spun.ink`. Ten days rather than a longer period because it is what our own sub-processors
give us — AppSignal's addendum allows ten — and a window we cannot be given is a window we cannot
honestly promise you. If you object, we will either continue without the change for your account or,
where that is not reasonably possible, tell you so — and you may then terminate the affected service
free of charge, with no early-termination penalty and with the switching and export rights in the
**Terms of Service**. We will not treat an objection as a reason to degrade or switch off your Site.

**11.3 Back-to-back terms.** Every sub-processor is bound by data protection obligations that are
the same in substance as ours under this agreement, in a written contract. Annex 2 names the
contract for each one.

**11.4 Our liability stays ours.** Where a sub-processor fails to meet its data protection
obligations, we remain fully liable to you for its performance (Art. 28(4) GDPR).

**11.5 Notices we pass on.** Where a sub-processor notifies us of an incident, a data-subject
request or a change to its own sub-processors that affects your data, we forward it to your account
e-mail address.

**11.6 The account e-mail is the channel — and it cannot currently be corrected by self-service.**
Both the sub-processor notices in 11.2 and the breach notices in section 13 go to the e-mail address
on your account. You must keep that address monitored and reachable. Be aware that spun.ink has
**no tool to change it today**: `/recover` only re-sends a link to the address already on file, and
there is no `update_account` tool yet. If the address on your account is wrong, write to
`support@spun.ink` and we will correct it by hand.

## 12. International transfers

**12.1** All storage of the personal data covered by this agreement is in the EU — `europe-west1`
(Belgium), and the Netherlands for the diagnostic data in Annex 2.1, backed up within the EEA.
**A transfer to a third country nevertheless exists**: Google LLC in the United States is
an authorised sub-processor of Google Cloud EMEA Limited for data-centre operations, service
maintenance and technical support, and Google provides support on a follow-the-sun basis. We will
not tell you that no third-country transfer takes place.

**12.2 Safeguards.** The primary safeguard is the **EU-U.S. Data Privacy Framework**, on which the
European Commission adopted an adequacy decision — Commission Implementing Decision (EU) 2023/1795
of 10 July 2023. The fallback safeguard is the **standard contractual clauses in Commission
Implementing Decision (EU) 2021/914**, incorporated into the Google Cloud Data Processing Addendum.
Details, entity names and where to obtain copies: **Annex 3**.

**12.3** Any onward transfer is subject to the same authorisation and objection mechanism as any
other sub-processor change (section 11).

## 13. Personal data breaches

**13.1** We notify you of a personal data breach affecting the personal data covered by this
agreement **without undue delay after becoming aware of it**, as Art. 33(2) GDPR requires. Our own
target is **within 48 hours of becoming aware**. The clock starts when City of Code becomes aware —
not when a sub-processor becomes aware.

**13.2** The notice goes to the account e-mail address (see 11.6) and contains, as far as we know it
at the time: the nature of the breach, the categories and approximate number of data subjects and
records concerned, the likely consequences, the measures taken or proposed, and a contact point for
more information. Where we cannot give all of it at once, we send it in phases without undue further
delay.

**13.3 The 72-hour notification to the supervisory authority is yours**, not ours, for the data
covered by this agreement — you are the controller (Art. 33(1) GDPR). The same applies to informing
the affected people where Art. 34 requires it. We assist you (section 16).

**13.4** We do not notify your Visitors on our own initiative, and we do not notify a supervisory
authority on your behalf, unless you ask us to and we agree in writing.

**13.5 Honest status.** A written incident-response plan is an open item; today the response follows
the operational runbook and the security review discipline described in Annex 1. Annex 1 marks it as
*planned*.

## 14. Orders from authorities and courts

**14.1** If an authority or a court orders us to hand over personal data covered by this agreement,
we **inform you without delay** and refer the authority to you as the controller — unless the law
that binds us forbids us to inform you.

**14.2** We disclose only what the order actually requires, and only after checking that the order is
legally binding on us.

**14.3** This section covers orders addressed to **us**. Orders about the *content* of your Site —
including orders under the Digital Services Act — are handled as described in the **Terms of
Service** and are not processing on your instruction (see section 6).

**14.4** The **Legal notice** (`/legal/imprint`) publishes, at the anchor `#data-act`, which jurisdiction
governs the ICT infrastructure used for the service and what measures exist against unlawful access
by third-country authorities.

## 15. Deletion and return at the end (Art. 28(3)(g) GDPR)

**15.1 Your choice.** At the end of the provision of the services, you choose whether we delete the
personal data covered by this agreement or return it to you. **If you do not tell us otherwise,
deletion applies.**

**15.2 How return works today — honestly.** The return path is the **MCP read tools of your
account**: the content, template, collection, blog, form, submission, asset and revision reads,
which give you your data in structured JSON. **There is no `export_account_data` tool. We are not
promising one here.** The **Terms of Service** carry the switching and export rights under the Data
Act, the exhaustive list of exportable categories, and the 30-day transition; this agreement does not
repeat them.

**15.3 How deletion works.** Deleting your account erases, in one cascade: your account row, every
Site, every page and post with its blocks, every template, collection and record, every blog, every
form and every Submission, every revision and revision snapshot, the search index rows, and the
stored asset files themselves. `delete_submission` deletes one Submission row on its own.

**15.4 The honest exceptions.**

- **Backups at our infrastructure provider.** Deletion from active systems is immediate. Copies in
  the infrastructure provider's backup and replication systems are removed on that provider's
  schedule — **up to 180 days** under the Google Cloud Data Processing Addendum (a recovery period
  of up to 30 days, then deletion within a maximum of 180 days). We will not tell you it is
  instantaneous.
- **Diagnostic samples at our error-tracking provider.** A crash report written before the deletion
  is not reached by the cascade. It carries no Submission and no Content of its own, but an error
  message inside it can quote one (Annex 2.1), and it ages out on the provider's own schedule —
  **at most 60 days**, after which only aggregate figures remain. We do not delete it on request
  ahead of that; we can ask the provider to.
- **Log lines at the same provider.** A log line written before the deletion is likewise not reached
  by the cascade. It carries the account and Site identifiers rather than Content, and ages out on the
  provider's own schedule — **at most 5 days**. The same applies: we do not delete it on request ahead
  of that; we can ask the provider to.
- **Handle and domain tombstones.** When a Site that was ever public is deleted, spun.ink keeps a
  small record of the released handle and released custom domain, carrying the former account
  identifier, so that the address cannot immediately be taken over by someone else. This record
  contains no Content, no Submissions and no Visitor data. It is kept permanently.
- **Billing records.** Invoices and the customer record held at Stripe are **our own controller
  data**, not personal data processed on your behalf. Austrian tax law requires City of Code to keep
  them for **seven years** (§ 132 BAO). They are not returned or deleted under this agreement; the
  **Privacy Notice** covers them.

**15.5** Where EU or Austrian law requires us to keep something, we keep only that, and only for as
long as the law requires.

## 16. Helping you meet your own duties (Art. 28(3)(e) and (f) GDPR)

**16.1 Requests from data subjects.** You answer them; the tools of your account are how you do it.
`list_submissions` and `get_submission` serve access and portability, `update_content` and
`update_block` serve rectification, `delete_submission`, `delete_content` and `archive_asset` serve
erasure and restriction. Where those tools are not enough for a particular request, write to
`support@spun.ink` and we will assist you by appropriate technical and organisational measures, as
far as that is possible for us.

**16.2 Misdirected requests.** If a Visitor contacts spun.ink about data on your Site, we do not
answer it on the merits. We forward it to your account e-mail address **without undue delay, and as
a service commitment within three working days**, and we tell the person that you are their contact
and that they should address you. We may confirm to them that City of Code hosts the Site and acts
as processor. This three-working-day figure is a service commitment we set ourselves, not a
statutory deadline.

**16.3 The one-month clock is yours.** Art. 12(3) GDPR gives *you* one month to answer a data
subject, extendable by two further months for complex or numerous requests, and the answer must be
free of charge. We time our assistance so you can meet it, but we cannot meet it for you.

**16.4 Art. 32–36 assistance.** Taking into account the nature of the processing and the information
available to us, we assist you with: security of processing (Art. 32), breach notification to the
supervisory authority and to data subjects (Art. 33 and 34), data protection impact assessments
(Art. 35), and prior consultation (Art. 36). In practice this means Annex 1, the notice in section
13, and answering your questions in writing.

**16.5** No assessment we help you produce is legal advice, and none of it makes us responsible for
your own compliance decisions.

## 17. Information and audits (Art. 28(3)(h) GDPR)

City of Code is a micro-enterprise. The audit route is proportionate to that, and it is a real route:

**17.1** On written request to `support@spun.ink`, we make available all information necessary to
demonstrate compliance with this agreement — normally within 30 days.

**17.2** We answer a reasonable security questionnaire and provide a **written self-attestation**
against Annex 1, signed by a managing director.

**17.3** We pass on the **certifications and reports of our sub-processors** by reference — see
Annex 1, section E. We do not hold an ISO 27001 certificate or a SOC 2 report of our own, and this
agreement does not claim one.

**17.4** Where the information above is genuinely not enough, you may conduct or mandate an audit,
**at most once in any twelve-month period**, on at least 30 days' written notice, during business
hours, without disrupting the service, and under an appropriate confidentiality undertaking. A
supervisory authority's requirement, or a substantiated breach affecting your data, overrides both
the frequency limit and the notice period. On-site inspection at a data centre is not something we
can grant — those premises are our infrastructure provider's, and its own audit rights and reports
apply instead.

**17.5 (Business Customers only.)** We bear our own costs for 17.1 to 17.3. For an audit under 17.4
beyond one per twelve months where no breach and no authority requirement is involved, we may charge
our reasonable, evidenced costs, agreed in advance.

## 18. What you must do

You are the controller, and these are yours:

**18.1 Lawfulness.** You need a legal basis for everything your Site collects, and you must respect
the principles in Art. 5 GDPR — in particular, only collect what the purpose actually needs.

**18.2 Special categories.** If your Site is meant to collect data of the special categories in Art.
9 GDPR or criminal-offence data under Art. 10, tell us at `support@spun.ink` before you launch it, so
that we can take the higher risk into account in our measures. You remain responsible for the
additional conditions such data requires.

**18.3 Your Site's own legal pages.** Every Site you publish needs **its own privacy notice** and,
where the law requires one, **its own imprint**, as pages of that Site. spun.ink's legal documents
cover spun.ink, not your Site. The free-plan attribution banner is **not** an imprint for anybody
and must never be presented as one.

**18.4 Cookies and third-party code you inject.** spun.ink itself sets only strictly necessary
session and security cookies, described in the **Privacy Notice**. If you inject anything else
through your Site's `head_code` or templates — analytics, embeds, maps, fonts, pixels, chat widgets —
**you** are the controller for it and **you** need the consent mechanism it requires. **spun.ink
ships no consent tool**, no banner and no preference centre. If you need one, you build it into your
own templates.

**18.5 Consent must be real.** Never pre-tick a consent checkbox in one of your forms. spun.ink's
form consent primitive stores an explicit boolean — keep it unticked by default and make withdrawal
as easy as giving consent.

**18.6 Your own mail.** Mail you send to your Visitors is yours. In Austria, unsolicited electronic
mail is governed by § 174 TKG 2021; elsewhere, by the law that applies to you. spun.ink sends no mail
on your behalf.

**18.7 Your Agent and your operator tokens.** Everything done under any token of your account —
including tokens you issue to other people on the Agency plan — is your act. Where you issue an
operator token, you must pass the **Terms of Service**, the **Acceptable Use Policy** and the
confidentiality duties of this agreement down to whoever holds it.

**18.8 Keep the account e-mail reachable** (see 11.6). It is how you receive sub-processor notices
and breach notices.

## 19. Liability

**19.1** Art. 82 GDPR applies as written. A processor is liable for damage caused by processing only
where it has not complied with obligations of the GDPR specifically directed to processors, or where
it has acted outside or contrary to your lawful instructions.

**19.2 For consumers.** Nothing in this agreement limits or excludes our liability for personal
injury, or for damage we cause intentionally or through gross negligence. Statutory rights you have
as a consumer are unaffected — and a limitation that Austrian consumer law does not permit does not
apply to you.

**19.3 (Business Customers only.)** Any cap agreed in the **Terms of Service** applies to this
agreement as well, subject to § 879(3) ABGB, and it never covers intent or gross negligence, and
never bars you from obtaining a copy of your own data.

**19.4** We remain fully liable for our sub-processors (11.4).

## 20. Changes to this agreement

**20.1** We may change this agreement — for example when a sub-processor changes, when a measure in
Annex 1 changes, or when the law changes. Each version is published at a stable URL with its own
version date and content hash, and the previous version stays available.

**20.2** We tell you by e-mail to the account e-mail address **at least 30 days before** the change
takes effect, saying what changed, why, and when it takes effect. If you do not object before that
date, the new version applies to your account from then on. **If you object, or you would rather
leave, you may terminate free of charge with effect from the date of the change**, and we will not
charge you for any period after it. For a material change we may ask for a fresh, explicit
acceptance instead of relying on silence.

**20.3** Changes never apply retroactively, and a change never imposes an extra cost on you.

**20.4 Nothing is switched off because you have not accepted.** No Site is suspended, degraded,
unpublished or gated because an acceptance is missing or a change notice went unanswered. The only
consequence is that starting a *new* paid subscription requires a current acceptance.

**20.5** Sub-processor changes follow section 11.2 (10-day objection), not this section.

## 21. Governing law, venue, and how this ends

**21.1** Austrian law applies, excluding its conflict-of-law rules and the UN Convention on Contracts
for the International Sale of Goods. **If you are a consumer, you keep the mandatory protections of
the law of the country where you habitually live** — nothing here takes those away.

**21.2 For consumers**, the courts are those the law gives you; we do not agree a forum with you in
advance. **(Business Customers only.)** The exclusive venue is the competent court in Salzburg,
Austria.

**21.3** This agreement ends when the account ends, except for the deletion and return duties in
section 15, which survive until they are performed, and confidentiality, which survives without
limit.

**21.4** If a clause of this agreement is invalid, the rest stays in force. For consumers, an invalid
clause is simply not applied — it is not reduced to a still-permissible remainder.

## 22. How to reach us

| what | where |
|---|---|
| Data protection, this agreement, data-subject matters, sub-processor objections (section 11.2), general legal contact | `support@spun.ink` |
| Reports of illegal content on a hosted Site | `abuse@spun.ink` — see the **Terms of Service** |
| Postal | City of Code GmbH, Adnet 436, 5421 Adnet, Austria |

Languages: German and English. Your supervisory authority for complaints about our own processing is
the Austrian **Datenschutzbehörde** (`dsb.gv.at`); as a controller you may have another one.

---

# Annex 1 — Technical and organisational measures (Art. 32 GDPR)

**Status of this annex.** Everything under "in place" is a contractual commitment for as long as this
version is in force. Everything under "planned" is **descriptive and non-contractual** — it tells you
what we intend, not what exists. We would rather show you the gap than tick a box we cannot defend.
Section 10.3 governs changes.

## A. Confidentiality

**In place**

- **Structural tenant isolation.** Every record that belongs to a customer carries the account it
  belongs to, and the isolation is enforced by the framework at query level rather than by
  convention. A credential for one account cannot read or write another account's data. This is the
  platform's single most load-bearing control and it is covered by automated tests.
- **Site-level scoping** inside an account, so a token limited to one Site cannot reach another.
- **Physical access control** at the data centres of our infrastructure provider (Google Cloud,
  `europe-west1`), under that provider's own certified controls — see section E.
- **Credential handling.** Account bearer tokens and operator tokens are never stored in readable
  form; only a keyed digest is kept, and a lost token can only be rotated, never recovered.
- **Secret management.** Application secrets are held in Google Secret Manager, not in the code base
  or the container image.
- **Keyless workload identity.** The application authenticates to cloud services through workload
  identity federation; no long-lived service-account key files exist.
- **Least privilege** for the people who operate the service; production access is limited to those
  who need it.
- **Private object storage.** Uploaded assets live in a private bucket and are served only through
  signed, expiring URLs — never through a public bucket URL.

**Planned**

- Application-level encryption of the stored form-submission payload (`Submission#data`). Today it is
  encrypted at rest by the infrastructure provider (section D) but not additionally encrypted by the
  application. `[planned]`
- Signed individual confidentiality undertakings for everyone with production access (§ 6(2) DSG) —
  see 9.2. `[planned]`
- Periodic formal review of access rights. `[planned]`
- Pseudonymisation of stored submission payloads. `[planned]`
- Documented staff data-protection training records. `[planned]`

## B. Integrity

**In place**

- **Transport encryption.** TLS 1.2 or higher on every public connection, terminated at a Google
  external HTTPS load balancer. Certificates for custom domains are provisioned and renewed
  automatically through Google Certificate Manager.
- **Signed, expiring asset URLs** instead of public object URLs.
- **Log parameter filtering.** The application's logging filters credentials, e-mail addresses and
  **every form-submission parameter**, so submitted content does not reach the log stream. The HTTP
  front end's own request logging is switched off.
- **No IP address and no user agent are stored with a Submission** (see 4.4).
- **Content Security Policy** enforced by the application shell; each Site is served from its own
  origin so that one Site's scripts cannot reach another's.
- **Server-side validation** of every field against the schema its template declares, before storage.
- **Guarded outbound fetching.** When you ask us to fetch an asset from a URL, the fetcher is
  protected against server-side request forgery, identifies itself as `Spun-CMS/1.0`, and is capped
  in size.
- **Anti-abuse controls on public form endpoints** — origin checking, a hidden honeypot field and
  rate limiting.

**Planned**

- Documented input/transfer control logging beyond the application's standard request log.
  `[planned]`

## C. Availability and resilience

**In place**

- **Managed, replicated infrastructure** in `europe-west1`: a managed Kubernetes cluster for the
  application, a managed MySQL instance for the data, managed object storage for assets.
- **Automated database backups** provided by the managed database service.
- **Immutable revision snapshots** of your Content and templates, so a bad edit can be restored
  without a restore from backup.
- **Health checking and automated restart** of unhealthy application instances.
- **Infrastructure as code**: the deployment is reproducible from the repository.

**Note on shared infrastructure.** The managed database instance is shared with other applications
operated by City of Code; spun.ink's data lives in its own database schema with its own credentials,
and no customer of one account can reach another account's data (section A).

**Planned**

- A documented, tested restore procedure with a stated recovery-time objective. `[planned]`
- A documented retention ceiling and deletion concept for Submissions and for logs. · `[planned]`

## D. Encryption at rest

Data at rest — database, object storage, backups and logs — is encrypted by our infrastructure
provider under the security measures of the Google Cloud Data Processing Addendum. Application-level
encryption of the submission payload is listed under A as *planned*.

## E. Regular review, and our sub-processors' certifications

**In place**

- **Automated security review in the delivery pipeline**: a static security scanner and a dependency
  audit run on every change before it can be merged, alongside the full test suite and the
  house-rules check.
- **Adversarial security review of the platform** against a tenant-as-attacker threat model,
  documented in the repository.
- **Sub-processor certifications by reference** — we rely on them and do not restate them as our own:
  Google holds ISO/IEC 27001 certification and publishes SOC 2 and SOC 3 reports annually, and for
  Google Cloud Platform additionally ISO/IEC 27017 and ISO/IEC 27018 and a PCI DSS Attestation of
  Compliance; AppSignal B.V. is certified to ISO/IEC 27001:2022, and its addendum carries its own
  measures catalogue as Exhibit C; Stripe is a PCI DSS Level 1 service provider.

**Planned**

- **Art. 30(2) processor record** (see 10.4). `[planned]`
- A written incident-response plan with named roles and a rehearsal schedule (see 13.5). `[planned]`
- A recurring internal review of this annex against what is actually deployed. `[planned]`

**Not held.** City of Code holds no ISO 27001 certificate and no SOC 2 report of its own.

---

# Annex 2 — Sub-processors

**Stand: 2026-08-25.** Changes follow section 11.2: notice to the account e-mail address, 10 days to
object, back-to-back contractual terms, our full liability under Art. 28(4) GDPR. **Both rows below
predate the first customer account**, so neither was preceded by a notice — there was nobody to
notify. From here on, every addition to or replacement in this list is announced first.

## 2.1 Sub-processor of the personal data covered by this agreement

| Entity | Role | Services | Location of processing | Contract |
|---|---|---|---|---|
| **Google Cloud EMEA Limited**, Ireland — with **Google LLC** (United States), **Google Austria GmbH** (Austria) and **Google Belgium NV** (Belgium) as its authorised group sub-processors for data-centre operations, service maintenance and technical support (the current relevant entries on Google's own group sub-processor list; that list, linked in the Contract column, governs if it changes) | Sub-processor under Art. 28(4) GDPR | Google Kubernetes Engine (the application), Cloud SQL for MySQL (all stored data), Cloud Storage (uploaded assets, private bucket), Cloud Logging, Secret Manager, Certificate Manager (TLS for custom domains), Artifact Registry | Storage in `europe-west1` (Belgium); support and maintenance access from the United States and other Google locations (see Annex 3) | Google Cloud Data Processing Addendum (Customers) — `cloud.google.com/terms/data-processing-addendum`. Google's own sub-processor list: `cloud.google.com/terms/subprocessors` |

| **AppSignal B.V.**, Netherlands — with **Worldstream B.V.** (Netherlands, cloud infrastructure), **Amazon Web Services EMEA SARL** (subprocessing in Ireland, cloud infrastructure and hosting) and **Hetzner Online GmbH** (Germany, optional hosted OpenTelemetry collector) as its own authorised sub-processors, the three named in Exhibit B of the addendum in the Contract column | Sub-processor under Art. 28(4) GDPR | Error tracking and performance monitoring for the platform. It receives **diagnostic data only**: the exception class and message, the backtrace, the controller action, the request path, the host, timings, and a fixed allow-list of request headers. Request parameters, session data, Visitor IP addresses, cookies, the authorisation header and query strings are switched off in our deployment and are **not transmitted**. Content or a Submission value can nevertheless appear **incidentally inside an error message** — which is exactly why this is a sub-processing relationship and not a mere recipient. Diagnostic samples are kept for **at most 60 days**, after which only aggregate figures remain. It also receives **application log lines at warning level and above**, plus the operational events we write deliberately: each is an event name with the request identifier, the account and Site identifiers and, where an exception is involved, its class and message. The same switches apply to them — no parameters, no session data, no Visitor IP address, no query string — and the same incidental quoting is possible, for the same reason. **Log lines are kept for at most 5 days** | Netherlands, Ireland and Germany. **No processing outside the EEA**: § 6.1 of the addendum states that AppSignal processes personal data under it exclusively within the EEA and does not transfer it out | **AppSignal Data Processing Addendum, version 5.0 (April 2026)**, reference `ZEGZ3-H8DPK-9CFS8-2SHXG`, signed by both parties on 2026-08-24. Its Exhibit B is the authorised sub-processor list, its Exhibit C the security measures. A copy is available from us on request at `support@spun.ink` |

That is the whole list. There are exactly two sub-processors of your Visitors' data, and the second
one receives only what a crash report contains.

## 2.2 Listed for completeness — **not** processors of the data covered by this agreement

These two touch **City of Code's own** controller-side data. They are named here so that you are not
left wondering, not because they process your Visitors' data.

| Entity | Role | What it actually handles | Location | Contract |
|---|---|---|---|---|
| **Google Ireland Limited** | City of Code's own processor under Art. 28(1) GDPR — **not Customer data** | The Google Workspace SMTP relay that carries spun.ink's own account mail (verification, recovery, deletion, billing and legal notices) to the account e-mail address. No Content, no Submissions, no Visitor data pass through it. | Ireland / EU | Google Cloud Data Processing Addendum (which now also covers Google Workspace) |
| **Stripe Payments Europe, Limited**, Ireland — with **Stripe, Inc.**, United States | Recipient and **independent controller** — **not Customer data**, and not a sub-processor under this agreement | Account and billing data only: the account e-mail address, the legal or trading name, billing address, VAT identification number, payment details, invoices and receipts. Stripe also processes this for its own purposes — fraud prevention, anti-money-laundering and know-your-customer checks, and product development — under its own privacy policy at `stripe.com/privacy`. | Ireland; United States (see Annex 3) | Stripe Data Processing Agreement, incorporated in the Stripe Services Agreement. |

## 2.3 Explicitly not a sub-processor: any AI model vendor

**Anthropic, OpenAI, Google or any other model vendor is not a sub-processor of spun.ink**, and none
appears in this annex. spun.ink makes no model calls. The only Anthropic component in the platform is
an open-source software library that implements the MCP protocol — a dependency, not a service, and
it sends nothing anywhere. Where your Agent puts your Visitors' data into a model, that is your
processing chain, on your instruction (section 7), and the vendor is **your** processor.

## 2.4 Changelog

| Version | Change |
|---|---|
| 2026-08-18 | First published list. |
| 2026-08-24 | **AppSignal B.V.** added as a sub-processor for error tracking and performance monitoring. Added while spun.ink had no customer accounts, so no section 11.2 notice was due and none was sent. Every later change to this list is announced first, with the 10 days to object that section 11.2 gives. |
| 2026-08-25 | AppSignal row corrected against the signed **AppSignal Data Processing Addendum 5.0**, which we did not hold when the row was written: **Hetzner Online GmbH** (Germany) added as a third AppSignal sub-processor, Amazon Web Services EMEA SARL's processing located in **Ireland** rather than Luxembourg, and the contract named by version, reference and signature date. No sub-processor was engaged or replaced by this correction — the list now matches what was already true. Section 11.2's objection window shortened from 14 days to 10. |
| 2026-08-25b | The AppSignal row widened: besides crash reports and timings, AppSignal now also receives our **application log lines at warning level and above** and the operational events we write deliberately, kept **at most 5 days**. No sub-processor was engaged, replaced or removed — the same company receives a wider category of data, and the switches that keep parameters, session data, Visitor IP addresses and query strings out of it are unchanged. Written while spun.ink still had no customer accounts, so no section 11.2 notice was due and none was sent. |

---

# Annex 3 — International transfers

| Transfer | Why it happens | Primary safeguard | Fallback safeguard | Where to get a copy |
|---|---|---|---|---|
| **Google LLC (United States)** receives access to the personal data covered by this agreement in the course of data-centre operations, service maintenance and technical support for Google Cloud EMEA Limited | Google provides operations and support on a follow-the-sun basis; storage stays in `europe-west1` | Adequacy under the **EU-U.S. Data Privacy Framework** — Commission Implementing Decision (EU) 2023/1795 of 10 July 2023 | **Standard contractual clauses**, Commission Implementing Decision (EU) 2021/914, as incorporated in the Google Cloud Data Processing Addendum | The Google Cloud Data Processing Addendum and the clauses it incorporates are published by Google; a copy is available from us on request at `support@spun.ink` |
| **Stripe, Inc. (United States)** receives account and billing data — **not** the data covered by this agreement | Stripe operates its platform from the United States | EU-U.S. Data Privacy Framework | Standard contractual clauses, Decision (EU) 2021/914, via Stripe's Data Transfers Addendum | `stripe.com/legal/dpa` and `stripe.com/legal/dta`; a copy from us on request |

**Honest caveats.**

- Data Privacy Framework certification is **per recipient and revocable**. We rely on the adequacy
  decision, not on a promise that either recipient will stay on the list: the current entries are
  public at `dataprivacyframework.gov`, and the standard contractual clauses named above are the
  fallback that carries the transfer if a certification lapses or the adequacy decision falls.
- We do not claim EU-only processing. We claim EU-only *storage*, with the transfers above.

---

# Annex 4 — Data flows

A short map of where the personal data covered by this agreement actually goes. Nothing here creates
a right or a duty; sections 3 to 7 do that.

| Flow | Trigger | Destination | Notes |
|---|---|---|---|
| A Visitor submits a form | Visitor action on your Site | Cloud SQL, `europe-west1` | Fields, form name, account, site, time. No IP, no user agent. |
| A Visitor loads a page | Visitor action | Rendered from Cloud SQL through the application; assets from Cloud Storage over signed URLs | The last **published** snapshot is what the public sees, not your working draft |
| You or your Agent read a Submission | `get_submission` / `list_submissions` over MCP | **Your Agent's context, and from there your model vendor** | Section 7. Your controller decision, your processing chain |
| You upload or fetch an asset | `upload_asset` over MCP | Cloud Storage, private bucket, `europe-west1` | Fetch-by-URL is SSRF-guarded and size-capped |
| You publish, restore or snapshot | `publish_content`, `checkpoint`, `restore_revision` | Immutable revision snapshots in Cloud SQL | Snapshots outlive the edit they replaced, by design |
| Your Site's search | Visitor search, and writes that change indexed text | A derived search table in Cloud SQL | Derived from Content you published |
| Operational logs | Every request | Cloud Logging | Credentials, e-mail addresses and all submission parameters are filtered out |
| An error or a slow request | A crash or a measured request | AppSignal, Netherlands | Exception, backtrace, action, path, host, timings. No parameters, no session data, no Visitor IP, no query strings. Kept at most 60 days |
| An application log line | A warning or an error our software records | AppSignal, Netherlands | The log message with its event name, the request identifier and the account and Site identifiers. No parameters, no session data, no Visitor IP, no query strings. Kept at most 5 days |
| Account mail to you | Verification, recovery, deletion, notices | Google Workspace SMTP relay → your account e-mail | Our own controller data, not yours (Annex 2.2) |
| Billing | Upgrading, paying, invoicing | Stripe | Our own controller data, not yours (Annex 2.2) |

---

## The other spun.ink legal documents

| Document | Address |
|---|---|
| **Terms of Service** — the contract; this agreement is part of it | `https://spun.ink/legal/terms` · `…/terms.md` |
| **Privacy Notice** — what City of Code does with data as controller | `https://spun.ink/legal/privacy` |
| **Legal notice** — imprint, disclosure, contact points, Data Act information | `https://spun.ink/legal/imprint` |
| **Acceptable Use Policy** — what may and may not be hosted | `https://spun.ink/legal/acceptable-use` |
| **Right of withdrawal** — the consumer withdrawal instruction and model form | `https://spun.ink/legal/withdrawal` |
| **Data Processing Agreement** — this document | `https://spun.ink/legal/dpa` · `…/dpa.md` |

Each is published as HTML and as raw markdown at a stable address, with no login and no JavaScript
required.
