From afe2c94a0eb577777ff52549c18a52b13c62f82e Mon Sep 17 00:00:00 2001 From: Davide Farella Date: Sat, 26 Sep 2026 20:12:46 +0200 Subject: [PATCH] The privacy policy and the deletion page both stores ask for Two static pages on oltre.space, privacy.html and delete-account.html, linked from the landing page footer with the public contact address. Every claim is checked against schema.sql, the live Neon project, the Cloud Logging buckets and the client. The pages say nothing about Apple token revocation, which is still #132. Also the store-launch checklist and its notes log under .ai/docs, the working record for the App Store and Play submissions. Co-Authored-By: Claude Opus 5.5 --- .ai/docs/store-launch-notes.md | 117 +++++++++++++++++ .ai/docs/store-launch.md | 221 ++++++++++++++++++++++++++++++++ site/index.html | 7 +- site/static/delete-account.html | 103 +++++++++++++++ site/static/privacy.html | 164 ++++++++++++++++++++++++ 5 files changed, 611 insertions(+), 1 deletion(-) create mode 100644 .ai/docs/store-launch-notes.md create mode 100644 .ai/docs/store-launch.md create mode 100644 site/static/delete-account.html create mode 100644 site/static/privacy.html diff --git a/.ai/docs/store-launch-notes.md b/.ai/docs/store-launch-notes.md new file mode 100644 index 00000000..873f279b --- /dev/null +++ b/.ai/docs/store-launch-notes.md @@ -0,0 +1,117 @@ +# Store launch — notes towards a reusable flow + +Opened 2026-09-16 on Davide's ask: *"I want you to take notes so we can create a reusable flow to +publish other apps. It could be some scripts, some CI automation, or even only some skills. Remember +the thing that I struggle with and that we need to double-check."* + +The checklist being worked is [`store-launch.md`](store-launch.md). This file is the *residue* — what +the next app should not have to rediscover. **What it becomes is decided when Oltre is live**, not +now: a global skill, a script in `.github/scripts/`, a CI job, or nothing. + +Three kinds of entry, and each one says which it is: + +- **TRAP** — something that looks fine and is not. A wrong default, an irreversible choice, a gate + that fires late. +- **FRICTION** — something that cost time and could be automated or written down once. +- **CANDIDATE** — a concrete thing to build: a script, a workflow, a skill, a template. + +--- + +## Traps + +- **TRAP — Play App Signing's default mints a new key.** Choosing it, rather than *"Provide a copy of + your app signing key"*, changes the SHA-1 the app is signed with. Any Google Sign-In Android OAuth + client is bound to package + SHA-1, so every Play install would fail to sign in, silently, with the + app looking fine. Irreversible in the sense that matters: the fix is registering a third OAuth + client and shipping a new release. *(Recorded in Oltre's `identity-provisioning.md` before we + started — the note is what made it cheap. That is itself the argument for this file.)* +- **TRAP — the 12-testers rule is decided by an account type chosen once, at registration.** A + personal Play account created on or after 2023-11-13 needs 12 testers opted in **continuously for + 14 days** before production access; an organization account is exempt but needs a legal entity, a + D-U-N-S number and 2–4 weeks of verification. It is a calendar decision made in a dialog most + people click through in five seconds. +- **TRAP — an app that requires sign-in pulls in three obligations at once**, and none of them is + obvious from the code: Apple's mandatory Sign-In Information for the reviewer (2.1(a)), in-app + account deletion (5.1.1(v)), and Play's **web** account-deletion URL on the Data Safety form. A + login screen is not a feature, it is a compliance surface. +- **TRAP — typed names shown to strangers trigger Apple guideline 1.2** (filter, report, block, + published contact) and Play's UGC policy. The trigger is the first review round that carries the + feature, so the cost lands a release after the feature ships. +- **TRAP — Play takes an AAB, the GitHub-release path builds an APK.** A publishing pipeline that + only ever produced APKs has a hole in it that only shows up at upload time. +- **TRAP — a generated privacy policy describes an app that has analytics and ads.** Publishing one + that overstates collection is itself a false privacy label. +- **TRAP — the Apple agreements gate is invisible until submission.** TestFlight works with an + expired or unaccepted Paid/Free Apps agreement; App Store distribution does not. Apple re-issues + the Program License Agreement periodically and the account silently sits at *Pending* until + somebody clicks through it in Agreements, Tax, and Banking. Check it **first**, not at submission. +- **TRAP — the public contact address ends up being a personal mailbox.** It goes on a privacy page, + a deletion page, both listings and (for a UGC app) the address Apple expects report responses from, + so it has to be per-product and send-capable, not a forwarding alias nobody replies from. +- **TRAP — the age-rating questionnaire changes under you.** Apple overhauled it in 2025 (new bands + 4+/9+/13+/16+/18+) and added Social Media questions in July 2026, **required for any submission + from September 2026**. Blog summaries lag behind, so read the questions off Apple's own + *Age ratings values and definitions* page on the day. Two answers set the floor: Social Media + forces 13+, and Unrestricted Web Access forces 16+. An auth sheet is not a web view. + +- **TRAP — a deferred compliance item reads as done.** Account deletion shipped, and the Apple token + revocation Apple pairs with it was deferred to an issue that stayed open + ([#132](https://github.com/fardavide/oltre/issues/132)). The checklist first said both had + shipped. Before filing any store answer, verify each compliance claim against the code with a grep + (`/auth/revoke`, SDK imports, the schema), not against docs or memory. +- **TRAP — App Privacy has more data types than the obvious one.** A game that keeps a server-side + save collects **Gameplay Content** ("saved games"), on top of the account's User ID. A screen name + is a **User ID** in Apple's taxonomy, not a Name. + +## Friction + +- **FRICTION — store requirements live in eight places**: App Review guidelines, App Store Connect's + own required fields, Play policy, Play Console's listing form, Data Safety, IARC, the brand + guidelines for each badge, and the screenshot size tables that change yearly. Nothing assembles + them per-app. +- **FRICTION — screenshot sizes are a moving target and the sources are SEO blogs.** For 2026: 6.9-inch + iPhone 1320×2868 required, 13-inch iPad 2064×2752 required when the app targets iPad, Apple scales + down for everything smaller; Play wants each side between 320 and 3840 px. Committed UI baselines + (393×852 here) fit neither store raw. +- **FRICTION — the assets a listing needs are not the assets an app needs.** Play's 1024×500 feature + graphic exists for no other purpose and had to be made from scratch, while the 512×512 icon was + already generated. +- **FRICTION — the subtitle took three rounds.** It is copy plus search terms in 30 characters. + What worked was grounding it in a reference game's real store listing (OGame's Play subtitle + *"Strategy in space: build colonies, research & fight for resources"*). Then treat subtitle + + keywords as **one search-term budget**: a word dropped from the subtitle moves to keywords rather + than disappearing. Mind the locale's spelling too: en-US says *colonization*, so a British + *colonisation* would miss US searches. + +## Candidates + +- **CANDIDATE — a `store-release` skill**: the ordered checklist with the traps inline, parameterised + by "does the app have accounts / UGC / iPad support", since those three answers generate most of + the obligations. +- **CANDIDATE — a screenshot-frame script**: take committed UI baselines, render them onto the exact + canvases each store demands (and nothing else), fail loudly on a size no store accepts. +- **CANDIDATE — a listing-copy template** in the repository rather than typed into two web forms: + short description, full description, keywords, review notes — one source, two stores. +- **CANDIDATE — the privacy + deletion pages as a generated pair**, from a small declaration of what + the server stores, so the page, the App Privacy answers and the Data Safety answers cannot drift. +- **CANDIDATE — `bundleRelease` beside `assembleRelease`** in the release workflow, plus the + service-account publish step, once the first manual upload has proved the listing. + +## To double-check when we get there + +- Whether Xcode Cloud has a start condition excluding `site/**`. `decisions.md` says *"a typo fix in + a privacy policy must not be able to cut a TestFlight build"*, but the template lives on `main` and + every `main` commit archives. Either the condition exists in the App Store Connect UI or the + sentence is wrong. +- Whether Apple accepts request logs (IP, 30 days) going undeclared as a data type. Apple has no IP + category, and the logs are infrastructure logging, but this is a reading of the definitions, not + a ruling. + +- Whether Play still accepts a 9:19.5 phone screenshot, or whether the 1080×1920 canvas is actually + required. +- Whether Apple's reviewer accepts *"sign in with your own Apple Account"* for an app whose server + creates the account on first sign-in — the theory is yes, the evidence is a review round. +- Whether the Android OAuth client's SHA-1 survives the Play App Signing upload, proved by a Google + sign-in from a Play-installed build and nothing less. +- Whether the iOS build number and `MARKETING_VERSION` line up with what App Store Connect will + accept for a first public release, rather than a TestFlight one. diff --git a/.ai/docs/store-launch.md b/.ai/docs/store-launch.md new file mode 100644 index 00000000..27920561 --- /dev/null +++ b/.ai/docs/store-launch.md @@ -0,0 +1,221 @@ +# Store launch — the live to-do + +The working checklist for putting Oltre on the **App Store** and **Google Play**, and then putting +the two store buttons on the README and on oltre.space beside a smaller APK link. + +**How this file is used.** One line per item, each owned by either *Davide* (a portal, an account, a +payment, a decision) or *the build* (a repository change). Tick as we go; nothing is ticked on the +strength of "should work". Delete the file when the two listings are live and the buttons are up — +anything worth keeping moves into `identity-provisioning.md` or `decisions.md` first. + +Status legend: `[ ]` open · `[~]` in progress · `[x]` done · `[!]` blocked on a decision. + +**Order, Davide 2026-09-16: the App Store first.** Play Console would not load, so registration moves +to 2026-09-17; §4 and the two pages in §5 run ahead of §2 and §3. The public contact address is +`oltre@fardavide.dev` on Davide's own domain — pending his confirmation, and named in exactly one +place in the generated pages so it is one edit if it changes. + +--- + +## 0. What is already true + +Facts read out of the repository on 2026-09-16, so no step below re-establishes them. + +- Apple Developer Program membership exists — team `A7Q83J6LR4`. Xcode Cloud archives every `main` + commit to **TestFlight internal testing**, so an App Store Connect **app record already exists** + for `dev.fardavide.oltre`. Read off App Information on 2026-09-26: Name **Oltre**, SKU + `OLTRE-IOS`, Apple ID **`6798498388`**, primary language English (U.S.), standard licence + agreement. So the App Store button's URL is `https://apps.apple.com/app/id6798498388` — it + resolves only once the app is live. +- Where the data lives, checked 2026-09-26 for the privacy page: Neon project `Oltre` in + `aws-eu-central-1` (Frankfurt) with **6 hours** of point-in-time history, so a deleted account + survives in restore history for at most 6 hours; Cloud Run in `europe-west1`; Cloud Logging's + `_Default` bucket (request logs — IP address, user agent) keeps **30 days**. No analytics, crash + reporting or push SDK in the client. +- Android ships as a **signed APK on GitHub Releases** (`release-android.yml`), from the keystore in + `~/Documents/Keys/Oltre/` whose SHA-1 is bound to the Google Sign-In Android OAuth client. +- One identifier across both stores: `dev.fardavide.oltre`. Version `0.25.1`, `targetSdk 36`, + `minSdk 26`. +- **In-app account deletion ships** (`AuthEndpoints.deleteAccount`, Settings → Delete account), so + guideline 5.1.1(v) is satisfied. **Apple token revocation does not** — nothing calls + `/auth/revoke` yet, and it is tracked as [#132](https://github.com/fardavide/oltre/issues/132). + Apple has asked for it since June 2022 of any app offering deletion and Sign in with Apple, so it + is a pre-submission item in §4. *(Corrected 2026-09-26: this line first said revocation shipped.)* +- **Sign-in is mandatory to play** — *"No colony is created until you are in"*. That pulls in the + reviewer sign-in note (Apple 2.1(a)), Play Data Safety, and Play's web account-deletion URL. +- **The roster shows typed commander names and typed alliance names to strangers**, and moderation + was deferred with an explicit trigger: *"Its trigger is an App Review round, not a sprint"* + (`alliance-sheet.md` §6, §"outside the epic"). This submission is that round. See §1. +- No privacy policy page and no terms page exist. oltre.space is one generated `index.html`. + +--- + +## 1. Decisions — Davide's, taken 2026-09-16 + +- [x] **UGC moderation ships before the App Store round.** A small slice — report a name, block a + member, a name filter, published developer contact — rather than hiding typed names or accepting + a guideline 1.2 rejection. Scoped in §7. +- [x] **The build writes the privacy policy and the deletion page**, Davide reviews before they go + up. Not a generator: a generated policy describes an app that collects analytics and serves ads, + neither of which is true here, and a false privacy label is itself a rejection. +- [x] **First Play upload by hand.** The build produces a signed AAB; Davide uploads it. Automation + is a follow-up and cannot run before a first release exists anyway. +- [x] **Play registers as a personal account, and the closed test is decided later.** Davide, + 2026-09-16. So production access on Play is gated on a 12-tester / 14-day closed test that has not + started — everything else (listing, AAB, App Store, moderation, the site) proceeds regardless, and + **Play production is the last thing that can go live**, not the first. The $25 registration is + still unpaid; the account does not exist until it is. + + The fork as it stood, kept because the next app faces it too: + - **Personal** — instant, and then **12 testers opted in continuously for 14 days** before + production access. The 14-day clock can run under everything else, so it costs two weeks of + calendar, not two weeks of work. + - **Organization** — exempt from the tester requirement, but needs a legal entity and a D-U-N-S + number, and verification runs 2–4 weeks (longer if the D-U-N-S has to be requested first). + + Whichever is chosen, **register today**: on the personal path the clock starts only once a closed + test is live, and the App Store half proceeds in parallel either way. + +--- + +## 2. Google Play — the account and the irreversible choice + +- [~] Davide: the Google account for it exists; the **$25 registration is not paid**, so there is no + developer account yet. Pay it, choosing the type §1 settles, and note the creation date. +- [ ] Davide: create the app — *Oltre*, game, free, and record the default language. +- [ ] **Play App Signing: choose "Provide a copy of your app signing key" and upload the existing + keystore.** Not the default, and irreversible. Letting Google mint a new key changes the SHA-1 + the Android OAuth client is bound to, and **every Play install fails to sign in** until a third + Android OAuth client is registered. `identity-provisioning.md` records this trap verbatim. +- [ ] Build: add a signed **AAB** to the release path — Play takes an App Bundle, not the APK the + GitHub release publishes. `:androidApp:bundleRelease`, same signing config. +- [ ] Davide: upload the first AAB to **internal testing** and install it from Play on his own phone. +- [ ] Verify **Sign in with Google still works from that Play-installed build** — the one check that + proves the signing-key choice landed right. A failure here is the SHA-1, nothing else. + +## 3. Google Play — the listing + +- [ ] Store listing: short description (80 chars), full description (4000), app icon + (`art/icon/android/play-store-512.png`, already generated), **feature graphic 1024×500 — does + not exist yet, the build generates it from `art/icon/threshold.svg`**. +- [ ] Phone screenshots (2–8). The Roborazzi baselines are 393×852; Play wants each side between 320 + and 3840 px, so they are rendered onto a 1080×1920 canvas rather than uploaded raw. +- [ ] Tablet screenshots — only if the listing declares tablet support. +- [ ] **Data safety** form: account identifier (`sub`) collected, linked to the user, not used for + tracking, purpose App Functionality — the same answers as the Apple App Privacy label, which + `identity-provisioning.md` §51 already decided. +- [ ] **Account deletion URL** on the data safety form — the web page from §5. +- [ ] Content rating questionnaire (IARC), target audience, ads declaration (none), news (no), + government (no), financial features (none). +- [ ] Privacy policy URL from §5. +- [ ] Closed test with 12 testers for 14 days — **required, and deliberately not started yet** (§1). + Nothing else waits on it; Play *production* waits on nothing else. +- [ ] Apply for production access, then release to production. + +## 4. App Store — the listing and the review + +- [ ] Davide: in App Store Connect, open the existing `dev.fardavide.oltre` record and fill the **App + Store** tab (TestFlight has never needed it). +- [ ] Screenshots: **6.9-inch iPhone** (1320×2868) is required, and because + `TARGETED_DEVICE_FAMILY` is `"1,2"` a **13-inch iPad** set (2064×2752) is required too. Apple + scales these down for every smaller device. Captured from the simulator, not from Roborazzi. +- [ ] Name, subtitle, keywords, description, promotional text, category (Games → Strategy), support + URL, marketing URL, copyright. + - [x] Name: **Oltre** (reserved with the record). + - [x] Subtitle: **`Online space colonization`**. Davide chose it on 2026-09-26. It's in OGame's + register without naming it, with *online* added at his request. It uses US spelling + because the primary language is English (U.S.), and search does not match across + spellings. Saved. + - [ ] Keywords must carry **`strategy`**, which the subtitle gave up for *online*. Subtitle and + keywords are indexed together, so a word in one is wasted in the other. + - [x] Category: Games, subcategories Strategy + Simulation, no secondary category. Saved. + - [x] Content Rights: *No* third-party content. Saved. +- [~] **Age rating: 4+.** Every answer below was checked against the code on 2026-09-26: no combat, + weapons, chat, ads, rankings or web view in any player-facing string. + - Parental Controls No · Age Assurance No. + - Unrestricted Web Access No: the Google sign-in sheet is an auth session, not browsing. + - **User-Generated Content Yes.** Typed commander and alliance names are shown to strangers. + Declaring it costs nothing at 4+, and hiding it would contradict the moderation slice. + - **Social Media No.** Davide decided this on 2026-09-26: there's no feed, only exact search + by name. *Yes* would force 13+ and a Social Media descriptor. + - Messaging and Chat No · Advertising No. + - Every Mature Themes, Medical, Sexuality and Violence item: None / No. + - Gambling No · Simulated Gambling None · Contests None · Loot Boxes No. Probe results are + random but never bought. +- [~] **App Privacy.** Data is collected: **Yes**. Two data types, each **App Functionality** only, + **linked** to the user, **not** used for tracking: + - **Identifiers → User ID.** This covers the provider `sub`, the surrogate account id, and the + commander name, since Apple's definition includes *"screen name, handle"*. This is §51 of + `identity-provisioning.md`. + - **User Content → Gameplay Content.** The colony save plus alliance names, seats and + contributions. Apple's definition names *"saved games"* and *"user-generated content + in-game"*. §51 missed this one. + - Not declared: email, which is verified in the token and discarded, and no device ID, since no + IDFA/IDFV/ANDROID_ID is read. Also no diagnostics, crash data, usage data or location. + Cloud Run request logs (IP, 30 days) are infrastructure logging; they are stated in the + privacy policy and not filed as a data type. + - [ ] Privacy Policy URL `https://oltre.space/privacy.html`, which resolves once §5 merges. +- [ ] **Apple token revocation, [#132](https://github.com/fardavide/oltre/issues/132)**, lands + before submission. +- [ ] **Sign-In Information**: the app requires sign-in, so the field is mandatory. The server creates + an account on first sign-in, so a reviewer signing in with their own Apple Account works — say + exactly that in the notes, or a rejection under 2.1(a) is the default outcome. +- [ ] Review notes: the game is asynchronous, so nothing visible happens in the first minute by + design. Say so, and say what to tap. +- [ ] Pick the build already on TestFlight, submit, answer the review. + +## 5. The two web pages both stores demand — the build's + +- [x] `site/static/privacy.html` is drafted on branch `store-launch-pages`. Every claim is checked + against `schema.sql`, the live Neon project, the Cloud Logging buckets and the client (no + analytics/push SDK, local notifications only). It deliberately says nothing about Apple + revocation until [#132](https://github.com/fardavide/oltre/issues/132) lands. +- [x] `site/static/delete-account.html` is drafted: the in-app steps, what goes and what stays, and + an email route for someone locked out. Oltre stores no email, so that route asks for a + commander name and alliance rather than promising a lookup that cannot exist. +- [x] Both are static files, copied verbatim by `build_site.py`, and linked from the landing page + footer with the contact address. A local build writes them and resolves every footer link. +- [ ] Davide reads both. Two claims are his to confirm: he is the **controller**, and the page + says Oltre is **not directed at children under 13**, which Play's target-audience form will + ask about too. +- [ ] Merge, which also cuts a TestFlight build, since every `main` commit does. Then paste the URL + into App Privacy. + +## 6. The buttons — README and oltre.space + +Blocked until the two listings are live; a store button that leads nowhere is a dead control. + +- [ ] `site/index.html`: two primary buttons — **App Store** and **Google Play** — and the APK + demoted to a smaller text-only button with a background. The APK's version, size and URL stay + derived from the published release; the two store URLs are constants. +- [ ] Store badges: Apple's and Google's official badge artwork, both of which carry brand rules + about size and clear space. Committed under `art/`, copied in by `ASSETS` in `build_site.py` so + a missing file fails the build rather than the page. +- [ ] `README.md` §Install: the same three, in the same order. +- [ ] A screenshot test or a build assertion is not available for the site; check the rendered page. + +--- + +## 7. The moderation slice — the build's + +Decided in §1. It is the compliance surface `alliance-sheet.md` §6 deferred, and both stores want the +same four things of an app that shows one player's typed text to another. + +- [ ] **A name filter** on what can be typed — commander name and alliance name, on the server, so an + old client cannot route around it. +- [ ] **Report** — a member on the roster, and an alliance in search results. It has to reach + somewhere a human reads. +- [ ] **Block** — a blocked commander's name and alliance stop being shown to the blocker. +- [ ] **Published developer contact** — an address on oltre.space and in the App Store listing, which + the privacy page in §5 needs anyway. +- [ ] Design round trip for the report and block faces, per `.ai/rules/session-roles.md`. +- [ ] Balance/design calls that are Davide's, collected before the slice starts rather than during. + +--- + +## 8. Notes for a reusable flow + +Kept in [`store-launch-notes.md`](store-launch-notes.md), on Davide's ask (2026-09-16): every step +that was friction, every thing that needs double-checking, and every candidate for a script, a CI +job or a skill — so publishing the *next* app is not this document again. What the notes become is +decided at the end, not now. diff --git a/site/index.html b/site/index.html index ecc56757..199d068e 100644 --- a/site/index.html +++ b/site/index.html @@ -549,7 +549,12 @@

Latest release

diff --git a/site/static/delete-account.html b/site/static/delete-account.html new file mode 100644 index 00000000..40115ba6 --- /dev/null +++ b/site/static/delete-account.html @@ -0,0 +1,103 @@ + + + + + + + + Delete your account — Oltre + + + + + + + +
+ ← Oltre +

Delete your account

+ +

In the app

+
    +
  1. Open Oltre and tap the settings button at the top of the screen.
  2. +
  3. Tap Delete account.
  4. +
  5. Tap Delete account again to confirm.
  6. +
+

+ It happens straight away, and it cannot be undone. Signing in again afterwards with the + same Apple or Google account starts a new, empty colony. +

+ +

What is deleted

+
    +
  • Your account, and the Apple or Google identifier it was linked to.
  • +
  • Your colony: facilities, research, ships, fleets, resources and experience.
  • +
  • Your commander name and mark.
  • +
  • Your seat in an alliance, your record of contributions, and any request to join one.
  • +
  • The records the server keeps to stop a command being applied twice.
  • +
+ +

What stays, and for how long

+
    +
  • + An alliance you founded or joined is not deleted with you. Its name, its tag and its + treasury stay, including what you paid in, which belonged to the alliance from the + moment you contributed it. Your name leaves its roster. +
  • +
  • The database's restore history holds deleted data for at most six hours.
  • +
  • Server logs, which carry IP addresses but no game data, are kept for 30 days.
  • +
+ +

If you cannot open the app

+

+ Write to oltre@fardavide.dev + and say whether you signed in with Apple or Google. Oltre does not store email addresses, + so it cannot find an account from one — include your commander name and your alliance, if + you had them, and we will work out with you which colony is yours before deleting it. + Requests are answered within 30 days. +

+

+ More about what Oltre stores is in the privacy policy. +

+ +
Oltre — all rights reserved.
+
+ + diff --git a/site/static/privacy.html b/site/static/privacy.html new file mode 100644 index 00000000..bd8405c7 --- /dev/null +++ b/site/static/privacy.html @@ -0,0 +1,164 @@ + + + + + + + + Privacy — Oltre + + + + + + + +
+ ← Oltre +

Privacy

+

Last updated 26 September 2026

+ +

+ Oltre is a game, and it keeps only what it needs to run your colony while you are away. No + analytics, no advertising, no tracking, and nothing is sold or shared for anyone's + marketing. This page says exactly what is stored, where, and for how long. +

+ +

Who is responsible

+

+ Oltre is made by Davide Farella, who is the controller of the data described here. Write to + oltre@fardavide.dev about anything on this page. +

+ +

What is stored, and why

+
    +
  • + An account identifier from Apple or Google. Signing in with Apple or + Google gives Oltre an opaque identifier that stands for your account with that provider, + and that identifier is what brings you back to the same colony on any device. Oltre does + not ask for your name. Your email address may travel inside the sign-in token; it is + checked and then discarded, never stored. +
  • +
  • + Your colony. The state of the game — facilities, research, ships, + fleets, resources, experience, and when each of them last changed — so it keeps + progressing while the app is closed and survives a new phone. +
  • +
  • + The commander name and mark you choose. Optional. They are shown to the + other members of an alliance you join or ask to join. +
  • +
  • + Alliances. The name and tag of an alliance you found, your seat and role + in one, when you joined, what you contributed to its treasury, and any request to join + that is still waiting. Other members see the roster; anyone can find an alliance by its + name. +
  • +
  • + Retry records. A short-lived note of each command already applied, so + one sent twice over a bad connection is not applied twice. They are pruned by age. +
  • +
  • + Server logs. The hosting provider records each request's IP address, + time, the address requested and the app's user agent. They are used only to keep the + service running and to defend it from abuse. +
  • +
+

+ On your device, the app keeps a copy of your colony and the session that keeps you signed + in. Notifications about fleets and probes are scheduled on the device itself; nothing is + sent to a push service. +

+ +

The legal basis

+

+ Everything above except the server logs is processed because it is necessary to provide + the game you signed up for. The logs are kept on the basis of a legitimate interest in + running a service that stays up and is not abused. +

+ +

Where it lives

+
    +
  • The server runs on Google Cloud Run in Belgium (europe-west1), and its logs are kept by Google Cloud.
  • +
  • The database is Neon, a Postgres host, on AWS in Frankfurt (eu-central-1).
  • +
  • Signing in is handled by Apple or Google, under their own privacy policies.
  • +
+

+ These providers process data on Oltre's behalf and for no purpose of their own. Nothing is + shared with anyone else. +

+ +

How long it is kept

+
    +
  • Your account, colony, profile and alliance seat: until you delete your account.
  • +
  • The database keeps six hours of restore history, so deleted data is fully gone six hours after you delete it.
  • +
  • Server logs: 30 days.
  • +
+ +

Your rights

+

+ You can see and change your commander name in the app at any time, and + delete your account from the app's settings, which + removes everything above that belongs to you. You can also ask for a copy of your data, ask + for it to be corrected or erased, or object to how it is used, by writing to + oltre@fardavide.dev. If you think your data has + been mishandled, you can complain to the data protection authority where you live. +

+ +

Children

+

+ Oltre is not directed at children under 13 and does not knowingly hold data about them + beyond what is described here. +

+ +

Changes

+

+ If this page changes, the date at the top changes with it, and the previous versions stay + in the project's history. +

+ + +
+ +