Squirrel Stash 隱私權政策
本文件以繁體中文為主,English follows below。兩個版本內容等價,若有衝突以英文版為準(App Store / Play Store 審查依據)。
繁體中文版
1. 我們是誰
「Squirrel Stash(松鼠票夾)」是一款獨立開發的票券管理 App。我們沒有帳號系統、不需登入,您的票券、優惠券、設定預設只儲存在您的裝置上。為了控管免費版 AI 辨識額度、防止濫用,我們有一個最小化的 Firebase 後端服務(Cloud Functions + Firebase 匿名驗證 + Firestore):Cloud Functions 代理 AI 請求與獎勵式廣告 / 預算檢查,並只記錄一個匿名 Firebase Auth UID與 AI 使用量/廣告獎勵/預算計數,不含您的票券內容,也不含姓名、email 等個人資料。詳見下方說明。
2. 我們收集哪些資料
| 類別 | 內容 | 儲存位置 | 是否離開您的裝置 |
|---|---|---|---|
| 票券 / 優惠券資料 | 標題、條碼、到期日、備註、自訂分類 | 本機 Hive 資料庫(AES-256 加密) | 否 |
| 票券截圖 | 您拍照或從相簿匯入的票券圖片 | 本機檔案系統(App 私有目錄) | 僅在使用 AI 辨識時上傳;上傳前會自動遮罩條碼(見第 3 節) |
| eSIM LPA 字串 | 電信商提供的 eSIM 啟用字串 | 本機 Hive(AES-256 加密) | 否(安裝時透過 OS 系統 URL 啟動) |
| 付費 / 訂閱資料 | Squirrel Pro 權益狀態:方案、到期日、產品 ID;訂閱驗證所需的最小平台資料 | 本機 SharedPreferences;Apple / Google IAP;Firebase Functions / Firebase custom claims | 購買由 Apple / Google IAP 處理;為驗證或還原 Pro 權益,App 可能將必要訂閱驗證資料送到 Squirrel 控制的 Firebase Function,並以匿名 Firebase Auth UID 更新 custom claim / 權益中繼資料 |
| App 使用記錄 | v1.1 上架版本預設關閉 telemetry;只有未來明確啟用且您主動同意時才會收集 | Firebase Analytics(目前停用) | 目前否 |
| 崩潰報告 | v1.1 上架版本預設關閉遠端崩潰回報;只有未來明確啟用且您主動同意時才會收集 | Firebase Crashlytics(目前停用) | 目前否 |
| 帳號識別 | 我們不要求註冊帳號,不會收集 email、電話、姓名 | 不適用 | 不適用 |
| 匿名 Firebase UID | Firebase 匿名驗證建立的 UID,用於驗證 Cloud Function 呼叫、AI 使用量 / 廣告獎勵 / 預算計數與訂閱權益中繼資料 | Firebase Auth / Firestore / Firebase custom claims | 是;這是 App 功能與防濫用用途,不是廣告追蹤,也不是 Squirrel Stash 自建的裝置識別碼 |
| 廣告 ID / 裝置 ID | Free 使用者啟動 AI 辨識並選擇廣告支援解鎖時,獎勵式廣告供應商可能依其 SDK 與平台政策處理廣告或裝置識別資訊(例如 ATT 同意後的 IDFA)。Squirrel Stash 不建立自己的裝置識別碼。 | 第三方廣告供應商;Squirrel Stash 自身不儲存自建裝置 ID | 僅限您主動選擇廣告支援解鎖時;我們不把票券內容、圖片、分類名稱、條碼或 AI 辨識結果提供給廣告供應商做投放 |
| 位置資訊 | 不收集 | 不適用 | 不適用 |
3. 圖片辨識(AI VLM):關鍵說明
當您使用「拍照新增票券」或「AI 辨識」功能時,App 會將處理後圖片送到 AI 模型供應商。1.1.2 版本使用下述 OpenAI 路徑。未來當 PCC 功能在您的 App 版本可用,且裝置為 iOS 27、Apple Intelligence 已開啟並符合系統條件時,App 會優先使用 Apple Private Cloud Compute(PCC)。其他情況,或 PCC 暫時無法完成辨識時,App 可能經 Squirrel 控制的 Firebase Cloud Function 轉送 OpenAI。您也可以改用不需上傳圖片的手動新增或本機條碼掃描。
3.1 條碼遮罩
我們在上傳前會用本機程式偵測條碼 / QR Code,並以黑色方塊覆蓋已偵測到的區域。圖片也會重新編碼為 JPEG,以移除 EXIF/GPS 中繼資料。這些動作在您的裝置上發生。
遮罩流程(概念虛擬碼,僅作說明用):
function maskBarcodes(image):
barcodes ← detectBarcodes(image) # 本機 ML 模型,不上雲端
if barcodes is empty:
return image (no masking needed)
canvas ← decode(image)
for each barcode in barcodes:
bbox ← barcode.bounds + 8px padding # 涵蓋條碼 quiet zone
canvas.fillRect(bbox, color=BLACK) # 純黑覆蓋
return encodeJpeg(canvas, quality=90)
偵測失敗或像素填充失敗時,App 會中止上傳而非送出未遮罩的原圖(強制中止,不降級)。
條碼可能包含兌換碼、eSIM LPA、會員號碼或付款 QR。遮罩已偵測到的區域可降低外洩與盜用風險,但無法保證每一個條碼都一定能被偵測。
3.2 我們會把圖片送到哪裡
| 供應商 | 模型 | 用途 | 隱私政策 | 資料保留 |
|---|---|---|---|---|
| Apple | Private Cloud Compute | 功能可用且符合條件時,iOS 27 裝置之優先圖片辨識路徑 | Apple PCC Security | Apple 將 PCC 描述為保有隱私保障的伺服器端模型;受裝置、地區、網路與每日配額影響 |
| OpenAI | gpt-5.4-mini / gpt-5.4 | PCC 備援;不支援 PCC 平台的主要路徑 | OpenAI policy | 請求設定 store: false;預設 abuse-monitoring logs 仍可能保留最多 30 天並有法律例外;API 資料預設不用於訓練,除非帳戶主動 opt in |
我們不使用 Apple PCC 與 OpenAI 以外的推論供應商。PCC 成功時,Squirrel 後端不會收到圖片或辨識結果。Free 使用者的後端會保存與匿名 Firebase UID 關聯的每日使用量計數、獎勵保留 / scan-session 識別碼、狀態與時間,用於額度與防濫用控管。OpenAI 路徑透過 Squirrel 控制的 Firebase Cloud Function,App 用戶端不內嵌 OpenAI API key。
我們無法控制 OpenAI 的政策變更。Squirrel Stash 提供的條碼遮罩是一道防線,但您仍應評估自身敏感資料的風險。如果您不希望任何圖片離開裝置,請不要使用 AI 辨識功能,改用手動輸入或條碼掃描(這兩個功能完全在本機運作)。
3.3 AI 成本、獎勵式廣告與同意選項
在 1.1.2 版本,Free 使用者可選擇觀看一次獎勵式廣告來解鎖該次辨識;Squirrel Pro 不需要觀看廣告。若未來版本啟用 PCC 每日免費辨識,App 才會在合格裝置上顯示當日已使用次數。Squirrel Stash 不會把票券內容、截圖、條碼、分類名稱、eSIM LPA 或辨識結果提供給廣告供應商做投放。
在 Google Mobile Ads 初始化或提出任何廣告請求前,App 會先透過 Google User Messaging Platform(UMP)更新所在地區適用的同意狀態,並在需要時顯示表單。只有 UMP 回報可提出廣告請求後才會繼續;法規要求時可從「設定 → 資料與隱私 → 廣告隱私選項」再次開啟表單。
UMP 與 Apple App Tracking Transparency(ATT)是不同控制:UMP 管理地區廣告資料處理同意,ATT 控制 IDFA 跨 App 追蹤。拒絕 ATT 不影響 App 功能,也不會替您回答 UMP;拒絕後廣告請求不得使用 IDFA 進行跨 App 追蹤。
3.4 隨同圖片傳輸的內容
為了讓 AI 模型給出更準確的分類結果,圖片之外我們會在 prompt 中夾帶:
- 您在「設定 → 自訂分類」建立的分類名稱列表(不含 icon / 顏色),讓模型可以建議現有的分類而非生造一個。如果您把公司名 / 個人標籤當分類名(例如「公司福委會」「老婆生日」),這些字串會出現在 prompt 中。如果不希望這類資訊離開裝置,請避免用敏感字串作為分類名稱。
- 您在「設定 → 國家偏好」的 active 國家清單(用於 eSIM 國別判定)
- 當下使用者選擇的 kind(ticket / coupon),讓模型解 ambiguous 案例
我們不會傳輸:
- 票券標題、備註、條碼內容、QR 內容(這些不需要 AI 來辨識,圖片本身就有)
- 您裝置上的其他票券 / 優惠券(每次 prompt 只看當下這張圖)
- Squirrel Stash 自建的裝置 ID(本 App 不建立這種 ID)、Apple ID、Google 帳號;AI prompt 也不包含廣告識別碼或匿名 Firebase Auth UID。廣告 SDK / Firebase 後端識別資訊的處理見第 2、3 節。
- 您圖片庫其他照片,僅限您主動選擇的當張票券圖片
4. 本機資料安全
- 所有票券 / 優惠券資料以 AES-256 加密儲存於 Hive 本機資料庫
- 加密金鑰存於系統安全儲存(iOS Keychain / Android Keystore),即使裝置 root / jailbreak 也無法直接讀取
- 截圖檔案存於 App 私有目錄,OS 層級已隔離其他 App 存取
5. 您的權利(GDPR / 台灣個資法)
5.1 存取 / 匯出
您隨時可以透過「設定 → 備份」匯出所有資料(加密 ZIP 檔)。
5.2 修改
所有資料皆可在 App 內直接編輯。
5.3 刪除
「設定 → 清除所有資料」會永久刪除所有本機票券、優惠券、截圖、設定,並 cancel 所有通知排程。
操作流程:
- 點擊「設定 → 清除所有資料」紅色按鈕
- 在彈出對話框中輸入「刪除」二字啟用確認鈕
- 點擊「清除所有資料」立即執行
明確會清除:本機 Hive boxes(包含加密的備份還原暫存快照)、所有截圖目錄、多數 SharedPreferences 設定、所有已排程的通知。
明確保留(白名單機制):
subscription_status/subscription_expiry_date/subscription_product_id:保留 Squirrel Pro 訂閱狀態,供 App 內顯示權益與恢復購買後離線判斷使用onboarding_completed_v1:首次教學旗標- Hive AES key:保留以確保未來匯入過去匯出的加密備份還能解密
注意 1:刪除本機資料不會回溯刪除過去送給 AI 供應商的圖片副本。如需向各供應商請求刪除,請參考其隱私政策。
注意 2:「設定 → 清除所有資料」是本機票券 / 優惠券 / 截圖 / 設定的刪除入口。若您也要要求刪除伺服器端以匿名 Firebase Auth UID 保存的 AI 使用量、獎勵式廣告 / 預算計數或訂閱權益中繼資料,請透過 support@squirrelwallet.app 聯絡我們;因為本 App 沒有帳號系統,若無法對應到特定匿名 UID,我們可能無法辨識您的伺服器端紀錄。
5.4 付費 / 訂閱
Squirrel Pro 透過 Apple App Store / Google Play 的 In-App Purchase 流程購買與還原。Squirrel Stash 不營運自己的付款處理系統,也不接收信用卡號或商店帳號密碼。為了驗證 / 還原 Pro 權益,App 可能將必要的 Apple 訂閱 claim / 平台驗證資料送到 Squirrel 控制的 Firebase Function,並以匿名 Firebase Auth UID 更新 Firebase custom claim / 權益中繼資料;App 也會在本機保存必要的訂閱狀態(方案、到期日、產品 ID)以顯示權益與離線判斷。
6. 兒童隱私
本 App 不刻意收集 13 歲以下兒童的資料。若我們發現意外收集,將立即刪除。
7. 政策變更
本政策若有重大變更,會在 App 內顯示提示,並更新本頁的 "Last updated" 日期。
8. 聯絡我們
- Email: support@squirrelwallet.app
English
1. Who we are
Squirrel Stash is an indie ticket / coupon management app. We have no account system and no login. Your ticket / coupon data is stored on your device by default. To enforce the free-tier AI-recognition quota and prevent abuse, we do run a minimal Firebase backend (Cloud Functions + anonymous Firebase Auth + Firestore): Cloud Functions proxy AI requests and reward / budget checks, and record only an anonymous Firebase Auth UID plus AI-usage, ad-reward, budget counters, and subscription entitlement metadata, never your ticket contents, and never personal data such as your name or email. See below for details.
2. What data we touch
| Category | Content | Storage | Leaves device? |
|---|---|---|---|
| Tickets / Coupons | Titles, barcodes, expiry, notes, custom categories | Local Hive DB (AES-256 encrypted) | No |
| Ticket screenshots | Photos you take or import | Local app-private dir | Only when AI recognition is invoked; barcodes are masked first (§3) |
| eSIM LPA | Carrier-provided activation string | Local Hive (AES-256 encrypted) | No (OS handles installation) |
| Paid purchases / subscriptions | Squirrel Pro entitlement status: plan, expiry, product ID; minimal platform data needed for subscription validation | Local SharedPreferences; Apple / Google IAP; Firebase Functions / Firebase custom claims | Purchase is processed by Apple / Google IAP. To validate or restore Pro access, the app may send necessary subscription validation data to a Squirrel-controlled Firebase Function and update custom claims / entitlement metadata keyed by the anonymous Firebase Auth UID. |
| Usage analytics | Disabled by default in v1.1; collected only if a future build explicitly enables telemetry and you opt in | Firebase Analytics (currently disabled) | Currently no |
| Crash reports | Remote crash reporting is disabled by default in v1.1; collected only if a future build explicitly enables it and you opt in | Firebase Crashlytics (currently disabled) | Currently no |
| Account IDs | We do not require sign-up | Not applicable | Not applicable |
| Anonymous Firebase UID | A UID created by Firebase anonymous auth to key AI-usage, ad-reward, budget counters, and subscription entitlement metadata | Firebase Auth / Firestore / Firebase custom claims | Yes; this is for App Functionality and abuse prevention, not ad tracking, and it is not a Squirrel-created device identifier |
| Ad IDs / Device IDs | When a Free user starts AI recognition and chooses the ad-supported unlock, the rewarded-ad provider may process advertising or device identifiers under its SDK and platform policies (for example IDFA after ATT consent). Squirrel Stash does not create its own device identifier. | Third-party ad provider; Squirrel Stash does not store its own device ID | Only when you choose the ad-supported unlock; we do not share wallet contents, images, category names, barcodes, or AI recognition results with ad providers for ad targeting |
| Location | Not collected | Not applicable | Not applicable |
3. AI Recognition (VLM): Important Disclosure
When you use the "scan ticket via AI" feature, the app sends a processed image to an AI model provider. Version 1.1.2 uses the OpenAI route described below. In a future version where PCC is available, an eligible iOS 27 device with Apple Intelligence enabled uses Apple Private Cloud Compute (PCC) first. Other cases, or a temporary PCC failure, may use a Squirrel-controlled Firebase Cloud Function to reach OpenAI. Manual entry and on-device barcode scanning remain available without uploading an image.
3.1 Barcode masking
Before any upload, the app detects barcodes / QR codes and blacks out the regions it detects on-device. It also re-encodes the image as JPEG to remove EXIF/GPS metadata.
Masking flow (conceptual pseudocode, illustrative only):
function maskBarcodes(image):
barcodes ← detectBarcodes(image) # local ML model, never leaves device
if barcodes is empty:
return image (no masking needed)
canvas ← decode(image)
for each barcode in barcodes:
bbox ← barcode.bounds + 8px padding # cover the barcode quiet zone
canvas.fillRect(bbox, color=BLACK) # solid black fill
return encodeJpeg(canvas, quality=90)
If detection or pixel-fill fails, the app aborts the upload rather than degrading to the unmasked original. There is no fallback path that sends the original image when masking partially fails.
Barcodes may contain redemption codes, eSIM LPA strings, membership numbers, or payment QRs. Masking detected regions reduces disclosure and redemption risk, but the app cannot guarantee that every barcode is always detected.
3.2 Where the masked image goes
| Provider | Model | Use | Privacy policy | Retention |
|---|---|---|---|---|
| Apple | Private Cloud Compute | Preferred route on eligible iOS 27 devices when the feature is available | Apple PCC Security | Apple describes PCC as a privacy-preserving server-side model; device, region, network, and daily quota requirements apply |
| OpenAI | gpt-5.4-mini / gpt-5.4 | PCC fallback; primary route where PCC is unsupported | OpenAI policy | Requests set store: false; default abuse-monitoring logs may still be retained up to 30 days with legal exceptions; API data is not used for training by default unless the account opts in |
We do not use inference providers beyond Apple PCC and OpenAI. When PCC succeeds, Squirrel's backend does not receive the image or result. For Free users it retains daily usage counters, reward-reservation and scan-session identifiers, status, and timestamps linked to the anonymous Firebase UID solely for quota and abuse prevention. The OpenAI route is proxied through a Squirrel-controlled Firebase Cloud Function, and the app does not embed an OpenAI key.
We do not control OpenAI's policy changes. Barcode masking is one line of defence. You should still assess the sensitivity of your data. If you prefer no image ever leaves your device, do not use AI recognition; use manual entry or barcode scanning instead (both run entirely on-device).
3.3 AI costs, rewarded ads, and consent choices
In version 1.1.2, Free users may choose one rewarded ad to unlock that AI recognition; Squirrel Pro does not require ads. If a future version enables the daily PCC allowance, the app will show today's usage on eligible devices. Squirrel Stash does not give wallet contents, screenshots, barcodes, category names, eSIM LPA strings, or recognition results to ad providers for ad targeting.
Before Google Mobile Ads is initialized or any ad request is made, the app uses Google's User Messaging Platform (UMP) to refresh the consent status required in the user's region and presents a form when required. The app proceeds only when UMP permits ad requests. Where required, Settings → Data & Privacy → Ad privacy choices opens the form again.
UMP and Apple's App Tracking Transparency (ATT) are separate: UMP governs regional advertising-data consent, while ATT controls IDFA access for cross-app tracking. Declining ATT does not disable app features or answer UMP on your behalf; ad requests cannot use IDFA for cross-app tracking.
3.4 What travels with the image (and what doesn't)
To help the model classify accurately, the prompt does include:
- The names of your custom categories (from Settings → Custom categories), so the model recommends an existing category rather than inventing one. If you used a personal tag (company name, partner's name) as a category name, that string travels with the prompt. If you don't want such strings to leave the device, avoid using sensitive text as category names.
- Your active country list from Settings (for eSIM region inference)
- The currently-selected kind (ticket / coupon), to break ambiguous ties
The prompt does NOT send:
- Ticket title / note / barcode payload / QR content (the image itself carries those; no need to duplicate over the wire)
- Other tickets / coupons on your device (each prompt sees the current image only)
- Any Squirrel-created device ID (the app does not create one), Apple ID, Google account; the AI prompt also does not include advertising identifiers or the anonymous Firebase Auth UID. Ad SDK / Firebase backend identifier handling is described in §§2 and 3.
- Other photos from your library. Only the one image you select is used.
4. Local data security
- All ticket / coupon data is AES-256 encrypted in the local Hive database
- The encryption key lives in the OS secure store (iOS Keychain / Android Keystore) and is unreadable even on rooted / jailbroken devices
- Screenshots live in the app-private directory, OS-isolated from other apps
5. Your rights (GDPR / TW PDPA)
- Access / Export: Settings → Backup exports all data as an encrypted ZIP
- Modify: Edit in-app
- Delete: Settings → Reset all data permanently removes all local tickets / coupons / screenshots / settings, the encrypted backup-restore recovery snapshot, and cancels notifications. Tap the red button → type "刪除" to enable confirm → tap "Reset all data". To request deletion of server-side AI-usage, rewarded-ad / budget counters, or subscription entitlement metadata stored under an anonymous Firebase Auth UID, contact support@squirrelwallet.app; because the app has no account system, we may be unable to identify your server-side records without a matching anonymous UID.
- Paid purchases / subscriptions: Squirrel Pro purchase and restore use Apple / Google IAP. Squirrel Stash does not operate a payment processor and does not receive card numbers or store account credentials. To validate / restore Pro access, the app may send necessary Apple subscription claim / platform validation data to a Squirrel-controlled Firebase Function and update Firebase custom claims / entitlement metadata keyed by the anonymous Firebase Auth UID; the app also stores the minimum local entitlement state needed for display and offline checks.
This does not retroactively delete image copies that AI providers may retain per their own policies. Contact each provider for their deletion process. Settings → Reset all data is the deletion entry point for local data; contact support@squirrelwallet.app for deletion requests covering identifiable server-side anonymous Firebase records.
6. Children's privacy
This app does not knowingly collect data from children under 13. If we discover such collection, we will delete it.
7. Changes to this policy
Material changes will be announced in-app and the "Last updated" date above will be revised.
8. Contact
- Email: support@squirrelwallet.app