From 95675f737900f90975d40685d12a7132c8021e33 Mon Sep 17 00:00:00 2001 From: Guilherme Biff Zarelli Date: Tue, 27 Oct 2026 15:23:20 -0300 Subject: [PATCH] Add Strava OAuth callback and privacy disclosures --- public/.well-known/assetlinks.json | 12 ++ .../velocimetro-alerta/privacidade/page.tsx | 172 ++++++++++++++---- .../strava/callback/page.tsx | 11 ++ .../callback/strava-callback-fallback.tsx | 60 ++++++ src/app/components/GoogleAnalytics.tsx | 18 +- 5 files changed, 231 insertions(+), 42 deletions(-) create mode 100644 public/.well-known/assetlinks.json create mode 100644 src/app/apps/velocimetro-alerta/strava/callback/page.tsx create mode 100644 src/app/apps/velocimetro-alerta/strava/callback/strava-callback-fallback.tsx diff --git a/public/.well-known/assetlinks.json b/public/.well-known/assetlinks.json new file mode 100644 index 0000000..57b9813 --- /dev/null +++ b/public/.well-known/assetlinks.json @@ -0,0 +1,12 @@ +[ + { + "relation": ["delegate_permission/common.handle_all_urls"], + "target": { + "namespace": "android_app", + "package_name": "br.com.helpdev.velocimetroalerta.v2", + "sha256_cert_fingerprints": [ + "FE:0E:92:C0:E8:6B:9F:7E:62:90:58:49:D6:33:33:24:E8:29:F6:88:44:F4:35:3C:D4:99:6A:6B:7D:94:95:B6" + ] + } + } +] diff --git a/src/app/apps/velocimetro-alerta/privacidade/page.tsx b/src/app/apps/velocimetro-alerta/privacidade/page.tsx index 857e67b..58eb762 100644 --- a/src/app/apps/velocimetro-alerta/privacidade/page.tsx +++ b/src/app/apps/velocimetro-alerta/privacidade/page.tsx @@ -13,7 +13,7 @@ export const metadata: Metadata = { }, }; -const updatedAt = '26 de outubro de 2026'; +const updatedAt = '27 de outubro de 2026'; export default function VelocimetroAlertaPrivacyPolicyPage() { return ( @@ -36,7 +36,8 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {

Esta política se aplica ao aplicativo gratuito Velocímetro Alerta para Android, publicado com o identificador br.com.helpdev.velocimetroalerta.v2. - O aplicativo não exige criação de conta e não oferece compras ou assinaturas dentro do app. + Os recursos locais podem ser usados sem conta. Uma conta Google é necessária para sincronizar algumas + preferências ou conectar o Strava. O aplicativo não oferece compras ou assinaturas dentro do app.

@@ -50,9 +51,9 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {

A localização e as métricas da atividade são processadas no dispositivo. A Help DEV não recebe esses - dados em seus servidores, não mantém uma conta de usuário para o app e o app não mantém um histórico - remoto das atividades. Os dados enviados ao Google Maps SDK ao exibir um mapa estão descritos na seção - abaixo. A permissão de localização é necessária para os recursos de velocidade e + dados no Firebase. Se você optar por enviar uma atividade ao Strava, os dados do arquivo GPX seguem + diretamente do aparelho para o Strava, conforme descrito abaixo. Os dados enviados ao Google Maps SDK ao + exibir um mapa estão descritos na seção abaixo. A permissão de localização é necessária para os recursos de velocidade e rastreamento; você pode recusá-la ou revogá-la nas configurações do Android, mas esses recursos podem deixar de funcionar.

@@ -93,16 +94,31 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {
-

Preferências e armazenamento

+

Conta Google, Firebase e preferências

- Preferências do app, como limites de velocidade, alertas, sensores configurados e zonas de frequência - cardíaca, ficam no armazenamento local do aplicativo. Conforme as configurações do aparelho e da conta, - o Android pode incluir dados locais do app em um backup ou transferi-los para outro dispositivo. Esses - backups são administrados pelo Android e pelo serviço de backup escolhido; a Help DEV não os controla. + O login Google é opcional para o uso local e necessário para sincronizar preferências e conectar o + Strava. Quando você entra, o Firebase Authentication processa identificadores da conta e informações de + perfil disponibilizadas pelo Google, como nome e e-mail. O Firebase Authentication opera em centros de + dados nos Estados Unidos. O Google trata esses dados conforme sua{' '} + + Política de Privacidade + . +

+

+ Se você escolher sincronizar, um conjunto limitado de preferências — incluindo opções de alertas, + intervalos, zonas de frequência cardíaca e a opção de sincronização automática — fica associado à sua + conta no Cloud Firestore do Firebase. O banco e as Cloud Functions do projeto estão configurados na + região de São Paulo; outros dados de serviço do Firebase podem ser processados pela infraestrutura global + do Google. As atividades salvas, arquivos GPX e estados de envio continuam no aparelho e não são enviados + ao Firebase. Mais informações estão na página de{' '} + + privacidade e segurança do Firebase + .

- O app não envia automaticamente localização, métricas de atividade ou preferências para um servidor e não - mantém um serviço próprio de histórico de atividades. + Preferências e atividades locais permanecem no armazenamento do aplicativo. Conforme as configurações do + aparelho e da conta, o Android pode incluí-las em um backup ou transferi-las para outro dispositivo; esses + backups são administrados pelo Android e pelo serviço de backup escolhido.

@@ -122,6 +138,28 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {

+
+

Conexão e envio de atividades ao Strava

+

+ Para conectar uma conta, você autoriza o Strava pelo navegador com a permissão de criar atividades + (activity:write). O código temporário de autorização é processado pelas Cloud Functions; os + tokens de acesso e renovação ficam no Firestore em um registro privado da sua conta. Quando a integração + estiver ativa, o segredo do aplicativo Strava fica no Google Secret Manager. Para enviar uma atividade, a função devolve ao aparelho + um token de acesso de curta duração, usado para enviar o GPX diretamente à API do Strava. A Help DEV não + recebe o arquivo GPX nem as coordenadas da atividade pelo Firebase. +

+

+ O envio manual transmite a atividade escolhida nos detalhes. Se você ativar Sincronizar + automático, atividades elegíveis salvas depois dessa escolha podem ser enviadas automaticamente; + atividades antigas não são enviadas em lote. O GPX pode conter trajeto, coordenadas, horários, elevação e, + quando disponíveis, frequência cardíaca, cadência, temperatura e umidade. O app também envia o nome, o + tipo e um identificador do arquivo. O Strava processa e armazena esses dados de acordo com a{' '} + + Política de Privacidade do Strava + . +

+
+

Anúncios, análise e identificadores

@@ -162,13 +200,27 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {

-
-

Retenção e exclusão

+
+

Retenção e exclusão de dados

As preferências, atividades salvas e rotas permanecem no dispositivo até você excluí-las em Minhas - atividades, limpar os dados do app nas configurações do Android ou desinstalá-lo. A Help DEV não mantém - um histórico remoto dessas atividades. Arquivos GPX exportados e cópias em backups devem ser excluídos - por você no serviço ou dispositivo em que foram salvos, conforme as opções desse destino. + atividades, limpar os dados do app nas configurações do Android ou desinstalá-lo. Preferências sincronizadas + ficam no Firestore enquanto o registro da conta existir; sair da conta Google no app não as exclui. + Quando a desconexão do Strava é concluída pelo app, a autorização é revogada e os tokens armazenados são + removidos. Atividades já enviadas ficam na conta Strava e devem ser excluídas por você diretamente no + Strava. Arquivos GPX exportados e cópias em backups devem ser excluídos no serviço ou dispositivo onde + foram salvos. +

+

+ Para solicitar a exclusão da conta Firebase usada pelo aplicativo, das preferências na nuvem e dos tokens + Strava associados, use o{' '} + + e-mail de suporte da Help DEV + {' '} + e informe o e-mail da conta Google usada no app. A solicitação remove a autorização e os tokens Strava + armazenados, mas não remove atividades já enviadas à sua conta + Strava nem os arquivos GPX que continuam no dispositivo; esses itens devem ser removidos nos respectivos + serviços ou no app.

@@ -193,7 +245,8 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {

This policy applies to the free Velocímetro Alerta Android app, package br.com.helpdev.velocimetroalerta.v2. - The app does not require an account and does not offer in-app purchases or subscriptions. + Local features can be used without an account. A Google account is required to sync some preferences or + connect Strava. The app does not offer in-app purchases or subscriptions.

@@ -206,11 +259,11 @@ export default function VelocimetroAlertaPrivacyPolicyPage() { settings. The app does not start tracking automatically.

- Location and activity metrics are processed on your device. Help DEV does not receive this data on its - servers, the app does not require a user account, and the app does not keep a remote activity history. - Data sent to the Google Maps SDK when a map is shown is described below. Location access is required for - speed and tracking features; you can deny or revoke it in Android settings, but those features may stop - working. + Location and activity metrics are processed on your device. Help DEV does not receive them through + Firebase. If you choose to send an activity to Strava, the GPX file goes directly from your device to + Strava, as described below. Data sent to the Google Maps SDK when a map is shown is described below. + Location access is required for speed and tracking features; you can deny or revoke it in Android + settings, but those features may stop working.

@@ -247,16 +300,30 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {
-

Preferences and storage

+

Google account, Firebase, and preferences

- App preferences, including speed limits, alerts, configured sensors, and heart-rate zones, are stored - locally by the app. Depending on your device and account settings, Android may include local app data in a - backup or transfer it to another device. Android and the backup service you choose manage those backups; - Help DEV does not control them. + Google sign-in is optional for local use and required to sync preferences and connect Strava. When you + sign in, Firebase Authentication processes account identifiers and profile information made available by + Google, such as your name and email address. Firebase Authentication operates from data centers in the + United States. Google handles this data under its{' '} + + Privacy Policy + . +

+

+ If you choose to sync, a limited set of preferences — including alert options, intervals, heart-rate + zones, and the automatic-sync setting — is associated with your account in Firebase Cloud Firestore. The + database and Cloud Functions are configured in the São Paulo region; other Firebase service data may be + processed across Google’s global infrastructure. Saved activities, GPX files, and upload statuses remain + on your device and are not sent to Firebase. See Firebase’s{' '} + + privacy and security information + .

- The app does not automatically send location, activity metrics, or preferences to a server and does not - maintain its own remote activity-history service. + Preferences and activities remain in the app’s local storage. Depending on your device and account + settings, Android may include them in a backup or transfer them to another device; Android and the backup + service you choose manage those backups.

@@ -275,6 +342,28 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {

+
+

Strava connection and activity uploads

+

+ To connect an account, you authorize Strava in a browser with permission to create activities + (activity:write). Cloud Functions process the temporary authorization code; access and + refresh tokens are stored in a private Firestore record for your account. When the integration is active, + the Strava application secret is held in Google Secret Manager. When an activity is sent, a function returns a short-lived access token + to the device, which uploads the GPX directly to Strava’s API. Help DEV does not receive the GPX file or + activity coordinates through Firebase. +

+

+ A manual upload sends the activity selected in its details. If you turn on Automatic sync, + eligible activities saved after you opt in may be uploaded automatically; existing activities are not + uploaded in a batch. A GPX file may contain the route, coordinates, timestamps, elevation, and, when + available, heart rate, cadence, temperature, and humidity. The app also sends the activity name, type, and + a file identifier. Strava processes and stores this data under its{' '} + + Privacy Policy + . +

+
+

Ads, analytics, and identifiers

@@ -311,13 +400,26 @@ export default function VelocimetroAlertaPrivacyPolicyPage() {

-
-

Retention and deletion

+
+

Data retention and deletion

Preferences, saved activities, and routes remain on your device until you delete them in My activities, - clear the app's data in Android settings, or uninstall the app. Help DEV does not keep a remote history - of these activities. You are responsible for deleting exported GPX files and backup copies from the - service or device where they were saved, using that destination's available options. + clear the app's data in Android settings, or uninstall the app. Synced preferences remain in Firestore + while the account record exists; signing out of Google in the app does not delete them. When you + disconnect Strava in the app, its authorization is revoked and stored tokens are removed. Activities + already uploaded remain in your Strava account and must be deleted there. Delete exported GPX files and + backup copies in the service or device where they were saved. +

+

+ To request deletion of the Firebase account used by the app, its cloud preferences, and associated Strava + tokens, use Help DEV's{' '} + + support email + {' '} + and include the email address of the Google account used in the app. The request removes the stored Strava + authorization and tokens, but it does not remove + activities already uploaded to your Strava account or GPX files that remain on your device; remove those + items in their respective services or in the app.

diff --git a/src/app/apps/velocimetro-alerta/strava/callback/page.tsx b/src/app/apps/velocimetro-alerta/strava/callback/page.tsx new file mode 100644 index 0000000..2a638f2 --- /dev/null +++ b/src/app/apps/velocimetro-alerta/strava/callback/page.tsx @@ -0,0 +1,11 @@ +import type { Metadata } from 'next'; +import StravaCallbackFallback from './strava-callback-fallback'; + +export const metadata: Metadata = { + title: 'Retorno do Strava — Velocímetro Alerta', + robots: { index: false, follow: false }, +}; + +export default function StravaCallbackPage() { + return ; +} diff --git a/src/app/apps/velocimetro-alerta/strava/callback/strava-callback-fallback.tsx b/src/app/apps/velocimetro-alerta/strava/callback/strava-callback-fallback.tsx new file mode 100644 index 0000000..e17b297 --- /dev/null +++ b/src/app/apps/velocimetro-alerta/strava/callback/strava-callback-fallback.tsx @@ -0,0 +1,60 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +const callbackPath = '/apps/velocimetro-alerta/strava/callback'; +const appPackage = 'br.com.helpdev.velocimetroalerta.v2'; +const playStoreUrl = 'https://play.google.com/store/apps/details?id=br.com.helpdev.velocimetroalerta.v2'; + +export default function StravaCallbackFallback() { + const [appIntent, setAppIntent] = useState(null); + + useEffect(() => { + const currentUrl = new URL(window.location.href); + const callbackParams = new URLSearchParams(); + for (const name of ['code', 'state', 'error']) { + const value = currentUrl.searchParams.get(name); + if (value) callbackParams.set(name, value); + } + + if (callbackParams.has('state') && (callbackParams.has('code') || callbackParams.has('error'))) { + const query = callbackParams.toString(); + const fallback = encodeURIComponent(playStoreUrl); + setAppIntent( + `intent://helpdev.com.br${callbackPath}?${query}` + + `#Intent;scheme=https;package=${appPackage};S.browser_fallback_url=${fallback};end` + ); + } + + window.history.replaceState(null, document.title, callbackPath); + }, []); + + return ( +
+
+

Velocímetro Alerta

+

Retorno do Strava

+

+ A autorização está voltando para o aplicativo. Se ele não abriu automaticamente, use o botão abaixo para + concluir a conexão. +

+ {appIntent ? ( + + Abrir o Velocímetro Alerta + + ) : ( +

+ Não encontramos os dados de retorno. Volte ao app e inicie a conexão com o Strava novamente. +

+ )} +

+ Se a conta não aparecer conectada em Conta e conexões, volte ao app e tente conectar + novamente. +

+
+
+ ); +} diff --git a/src/app/components/GoogleAnalytics.tsx b/src/app/components/GoogleAnalytics.tsx index 0be8a0a..7186396 100644 --- a/src/app/components/GoogleAnalytics.tsx +++ b/src/app/components/GoogleAnalytics.tsx @@ -6,17 +6,21 @@ export default function GoogleAnalytics() {