← 回到止损计时Back to Time & Effort Check-in

隐私政策

止损计时(英文版:Time & Effort Check-in)· 运营者 {{OPERATOR}} · 最后更新 2026-09-13

这份文件只描述本产品实际做的事。每一条都能在代码里找到对应实现,文件路径写在括号里,你可以自己对。

1. 不登录也能完整使用

产品的全部核心功能——设重评点、立即重评、决定、笔记、历史、复盘、导出——不需要注册,也不需要联网。不登录时数据全部写在你这台设备的浏览器 localStorage 里(键 sl.v2),不经过我们的服务器(public/app/storage.js)。

各浏览器的 localStorage 天然按「站点 + 设备」隔离:同一台电脑上换个浏览器就看不到,别人的设备更看不到。

2. 登录后我们存什么

只有你主动注册并登录,数据才会同步到我们在 Cloudflare Workers KV 上的存储。存的键与内容如下(functions/api/[[route]].js、functions/api/_lib.js):

存储键内容保留
data:{用户名}你的事项、轮次、决定、笔记,以及从旧版本迁移过来的原始快照直到你要求删除
user:{用户名}用户名与口令校验值。口令用 PBKDF2-SHA256、30000 次迭代加盐存储,我们没有你的明文口令直到你要求删除
token:{token}登录会话30 天后自动过期
tokens:{用户名}会话反向索引(最多 50 条),只为「改口令/找回后吊销全部会话」而存在同上
recovery:{用户名}找回码的哈希(PBKDF2 加盐)。明文找回码不落盘,只在生成时给你看一次直到重新生成
entitlement:{用户名} / ledger:{用户名}Pro 权益状态与变更台账(发放、撤销、退款留痕),台账最多 100 条直到你要求删除
order:{来源}:{订单号} / redeem:{哈希}订单去重标记、兑换码使用状态财务留痕需要,长期保留

我们不收集:你的真实姓名、手机号、位置、通讯录、设备标识符、IP 地理画像。注册只要一个你自己起的用户名和一个口令,不要求邮箱。

邮箱

界面里没有邮箱绑定入口。账户找回只有一条路:注册时给你看一次的 12 位一次性找回码。后端保留了邮箱接口,但没有可用的发信通道,所以不向你展示一个兑现不了的功能(docs/exec/BLOCKERS.md B06)。

访问日志

接口调用的限流按 Cloudflare 传来的 CF-Connecting-IP 在内存里计数(注册 5 次/小时、登录 10 次/5 分钟等),这个计数不写入存储、进程重启即消失。Cloudflare 作为托管方会按其自身政策保留边缘访问日志,我们不另行留存。

3. 匿名统计:默认关闭,随时可关

产品分析默认是关闭的(public/app/storage.js 里 analytics: false),关着也能完整使用。你在设置里主动打开后,才会发送以下内容,且仅限这些:

事项名称、你写的条件与假设、笔记、感受、成果文字、音频——一个字都不上传。 这不是承诺,是实现:服务端 functions/api/events/[[path]].js 逐字段过白名单,白名单之外的字段(包含任何自由文本)在入库前直接丢弃,连带那条事件一起丢。

服务端也不保存事件原文,只按 agg:{日期}:{事件名}:{平台} 累加一个整数计数(外加一个 7 天过期的去重标记 evdedup:{decisionId})。这份数据只能告诉我们「某天有多少次决定确认」,无法还原到某个人做了什么。

关掉开关即刻停止发送,已经累加的计数无法按人回溯删除——因为它从一开始就不知道那是谁。

4. 第三方

第三方拿到什么为什么
Cloudflare(Pages / Workers KV)托管页面与接口,存储上面第 2 节列的键本产品的服务器就是它
Lemon Squeezy(海外付款)你的付款信息由它处理,我们拿不到你的卡号。它回传给我们的只有订单号、下单邮箱、license key它是海外销售的记录商户(Merchant of Record)
微信(小程序内付款)付款在微信的虚拟支付里完成,我们只收到微信订单号与金额平台规则要求站内支付

除此之外没有别的第三方:没有广告,没有第三方统计 SDK,没有 A/B 测试平台,没有崩溃采集服务。网页不引入任何第三方脚本、字体、图标包或 CSS 库(这是产品的硬约束,见 README.md「设计约束」)。

本站不使用 cookie。 登录令牌与设置存在 localStorage 里,不随请求自动发往任何第三方,也不用于跨站追踪。因此这里没有 cookie 同意弹窗——因为没有要同意的东西。

5. 导出你的数据

应用内「导出」会把整包数据存成一个 JSON 文件(文件名形如 stop-loss-timer-20260913-142530.json),内容包括全部事项、轮次、决定、笔记,以及从旧版本迁移时留下的原始快照(public/app/storage.js 的 buildExport())。这是完整的、可读的、不打折的一份。

导出入口在这些地方都有:设置页、容量接近上限时的提示、同步冲突的三选一、以及登录时选择「仅用云端」而放弃本机那份数据的时候——被放弃的那份会直接给你一份导出,不静默丢掉。

6. 删除你的数据

删号会一并删掉 Pro 权益记录,删除后无法凭原账户恢复购买。想保留权益又想清空内容的,请单独说明,我们只删 data:。

订单去重标记(order:)与兑换码使用记录(redeem:)不随删号清除:它们是财务留痕,且不包含你的任何使用内容。

7. 传输与安全

全站走 HTTPS。口令以 PBKDF2-SHA256(30000 次迭代、随用户加盐)存储,我们自己也读不出明文。找回码同样只存哈希。改口令或用找回码重置时,该账户此前的全部登录会话立刻失效。

我们不做「无法被攻破」这种承诺。能说的是:我们没有在服务端存放明文口令、明文找回码,也没有存放任何我们不需要的个人信息。

8. 未成年人

本产品不面向 14 周岁以下儿童设计,也不主动采集年龄。如果你是监护人并认为孩子在这里留下了数据,按第 6 节联系我们删除。

9. 变更

这份政策变更时会改动页首的「最后更新」日期。涉及采集范围扩大的变更,会在应用内明示后再生效,不会静默改。

10. 联系

隐私相关的问题、导出协助、删除请求,都发到 support@{{DOMAIN}}。运营者:{{OPERATOR}}。

Privacy Policy

Time & Effort Check-in · Operated by {{OPERATOR}} · Last updated 2026-09-13

This page describes only what the product actually does. Every statement maps to code; the file path is in brackets so you can check it yourself.

1. Full use without an account

Every core feature — setting a reassessment point, reassessing right now, deciding, notes, history, review, export — works without signing up and without a network connection. While signed out, your data lives entirely in this device's browser localStorage (key sl.v2) and never reaches our servers (public/app/storage.js).

Browser localStorage is isolated by site and device: another browser on the same machine cannot see it, and neither can anyone else's device.

2. What we store once you sign in

Only if you choose to register and sign in does your data sync to our storage on Cloudflare Workers KV. The keys and their contents (functions/api/[[route]].js, functions/api/_lib.js):

KeyContentsRetention
data:{username}Your tasks, rounds, decisions, notes, plus the untouched snapshot migrated from older versionsUntil you ask us to delete it
user:{username}Username and password verifier. Passwords are stored with PBKDF2-SHA256, 30,000 iterations, per-user salt. We do not hold your plaintext password.Until deletion
token:{token}Sign-in sessionExpires automatically after 30 days
tokens:{username}Reverse index of sessions (max 50), kept only so a password change or recovery can revoke every sessionSame as above
recovery:{username}Hash of your recovery code (PBKDF2, salted). The plaintext code is never written to disk; it is shown to you once, at generation.Until regenerated
entitlement:{username} / ledger:{username}Pro entitlement state and its change ledger (grants, revocations, refunds), capped at 100 entriesUntil deletion
order:{source}:{id} / redeem:{hash}Order de-duplication markers and redeem-code usage stateRetained as a financial record

We do not collect your real name, phone number, location, contacts, device identifiers, or an IP-derived profile. Registration needs a username you invent and a password. No email address is required.

Email

There is no email-binding entry in the interface. Account recovery has exactly one path: the 12-character one-time recovery code shown to you once at registration. The backend keeps an email endpoint, but there is no working outbound mail channel, so we do not surface a capability we cannot deliver (docs/exec/BLOCKERS.md B06).

Access logs

API rate limiting counts requests in memory, keyed by the CF-Connecting-IP header Cloudflare provides (5 registrations/hour, 10 sign-ins/5 minutes, and so on). That counter is never persisted and disappears when the process restarts. Cloudflare, as our host, retains edge access logs under its own policy; we keep no separate copy.

3. Anonymous analytics: off by default, off whenever you want

Product analytics are off by default (analytics: false in public/app/storage.js), and everything works with them off. Only after you switch them on does the app send the following, and nothing else:

Task names, the conditions and hypotheses you write, notes, feelings, outcome text, audio — not one character is uploaded. This is not a promise but an implementation: functions/api/events/[[path]].js filters field by field against the allowlist, and anything outside it (including any free text) is discarded before storage, taking the whole event with it.

The server also stores no raw events — only an integer counter under agg:{date}:{event}:{platform}, plus a de-duplication marker evdedup:{decisionId} that expires after 7 days. This can tell us "how many decisions were confirmed on a given day"; it cannot be traced back to what any person did.

Turning the switch off stops sending immediately. Counters already incremented cannot be deleted per person, because they never knew who you were.

4. Third parties

Third partyWhat it receivesWhy
Cloudflare (Pages / Workers KV)Hosts the pages and API, stores the keys listed in section 2It is this product's server
Lemon Squeezy (international payments)Handles your payment details; we never receive your card number. It sends us only the order id, the purchase email and the license keyIt is the Merchant of Record for international sales
WeChat (in-mini-program payments)Payment happens inside WeChat's virtual payment; we receive only the WeChat order id and the amountPlatform rules require in-app payment

There are no other third parties: no advertising, no third-party analytics SDK, no A/B testing platform, no crash reporter. The web client loads no third-party script, font, icon pack or CSS library at all — a hard product constraint (see "design constraints" in README.md).

This site sets no cookies. Your sign-in token and settings live in localStorage, are never attached automatically to third-party requests, and are not used for cross-site tracking. That is why there is no cookie banner here: there is nothing to consent to.

5. Exporting your data

The in-app export writes the complete dataset to a JSON file (named like stop-loss-timer-20260913-142530.json) containing every task, round, decision and note, plus the original snapshot preserved during migration from older versions (buildExport() in public/app/storage.js). It is complete, readable, and not reduced in any way.

Export is offered in settings, in the warning shown as you approach the capacity limit, in the sync-conflict choice, and at sign-in when you choose "cloud only" and thereby discard the local copy — the discarded copy is handed to you as an export rather than silently dropped.

6. Deleting your data

Deletion also removes your Pro entitlement record; afterwards the purchase cannot be restored under that account. If you want to keep the entitlement but wipe the content, say so and we will delete only data:.

Order de-duplication markers (order:) and redeem-code usage records (redeem:) survive deletion: they are financial records and contain none of your content.

7. Transport and security

Everything is served over HTTPS. Passwords are stored with PBKDF2-SHA256 (30,000 iterations, per-user salt) and are unreadable to us. Recovery codes are likewise stored only as hashes. Changing your password or resetting via a recovery code immediately invalidates every existing session on that account.

We make no "unbreakable" claim. What we can say: no plaintext password, no plaintext recovery code, and no personal information we do not need is stored on our servers.

8. Children

This product is not designed for children under 14 and does not collect age. If you are a guardian and believe your child left data here, contact us as described in section 6 and we will delete it.

9. Changes

Any change updates the "Last updated" date at the top. Changes that widen what we collect will be shown in the app before they take effect; they will not happen silently.

10. Contact

Privacy questions, export help and deletion requests all go to support@{{DOMAIN}}. Operator: {{OPERATOR}}.