· compliance· 约 24 分钟精读

Parental Gate Consent Boundary Offline Kids App — Technical Analysis | KeyRotate Technology

核心要点速览 · TL;DR 概要

一款不联网、不注册、不采集数据的儿童教学应用,家长门到底守住了什么?本文以密旋科技 QubitLab 的真实源码为样本,做一次受守卫动作普查:六处入口全部指向付费墙,文凭导出与系统分享、学习进度重置、本地演示开关、家长报告页都不在守卫面上;门上的两位数乘法题能挡住误触,挡不住冒充,也证明不了坐在设备前面的是谁。据此拆开无账户场景下的同意表达、出口控制与能力边界。

Parental Gate Consent Boundary Offline Kids App — Technical Analysis | KeyRotate Technology

一、一款不联网的儿童应用,为什么还要有一道门

一台不联网、不注册、不采集数据的教学应用,从合规角度看似乎已经把最麻烦的部分绕开了:没有账户,就没有未成年人个人信息的收集环节,也就没有随之而来的同意取证负担。但把应用放进应用商店的儿童类别之后,还有另一套要求落在界面上——凡是会把用户带出内容区、或者产生支付与处置后果的入口,都应当设一道家长确认环节。

这条要求在有服务端的产品里很好实现:验证、记录、留痕都在云端完成,客户端只负责弹窗。而在端侧应用里没有任何一方可以充当裁判,门只能由本地代码自己立起来,用什么形式、守到什么程度,全由工程决定。

密旋科技的 QubitLab 就是这样一款应用:面向应用商店的移动端量子物理与 STEM 启蒙沙盒,96 关闯关、可交互的布洛赫球面、双比特逻辑门拼装,全程离线完成。本文不评价它的教学效果,而是把”家长门”这件小事拆开看:门由什么构成、立在哪些入口上、哪些入口没有门、一道本地算术题究竟能担保什么。以下事实全部来自该工程 62 个 Swift 源文件、三万两千余行的静态审查。

家长门守卫面普查:六处入口共用一个目标,四条面尚无门受守卫的入口(六处)① 奥德赛章节头|解锁全部② 锁定关卡卡|未购且非免费③ 沙盒实验工具栏|Pro④ 实验详情|解锁大师通行证⑤ 家长中心|升级按钮⑥ 设置页|升级按钮触发条件:未购买且未开演示态家长门两位数乘法题4 × 7 = ?答对即放行答错即换题无次数上限无冷却与锁定付费墙六处入口同一目的地内容解锁由权益判定负责同一设备上,四条面没有这道门文凭导出与系统分享学习进度重置教师演示开关家长中心报告

二、这道门长什么样:一道两位数的乘法题

门的实现只有一个视图文件,不申请任何系统权限,也不读写外部数据,只做三件事:出题、判题、回调。

出题的取值区间是固定的:两个因数各自在 4 到 9 之间随机选取,因此乘积落在 16 到 81 之间。这个区间是刻意的:两位数乘法正好落在”成年人几乎不会算错、低龄儿童通常算不出来”的带宽里。题目以等宽大字号呈现,因数经过一次固定映射后逐字渲染,答案输入框使用数字键盘,避免误触字母键。

判题环节有两条值得写明的细节。答对时先给一次成功触觉,再关闭门并执行回调;答错时给一次警示触觉,显示一行错误文案,然后立刻重新出题。也就是说,答错既没有次数上限,也没有冷却时间,更没有锁定策略——这是一道无状态的门,错误不累积、不记账、不阻断,重试的全部成本就是一道新的乘法题。取消按钮位于工具栏左上角,直接关闭门并且不执行回调,因此”主动取消”与”从未通过”在调用方看来是同一种结果:那个动作没有发生。

门的要素实现事实
题目因数本机随机,各自取 4 至 9
乘积范围16 至 81
答对语义成功触觉,关闭门并放行
答错语义警示触觉,显示错误文案,换题重来
重试次数无上限
冷却与锁定无
取消语义关闭门,不放行
走查参数判定直接短路放行
调试构建出题时自动填入正确答案

与自动化相关的接线还有两处。第一,门为答案输入框、确认按钮、取消按钮各注册了一枚可访问性标识,另有一枚留给调试构建里的自动求解按钮;这四枚标识让自动化测试可以在没有真人参与的情况下把这道门走通。第二,走查启动参数会让判定直接短路:携带该参数运行时,答案比较的条件恒真。调试构建更进一步,出题的同时就把正确答案填进了输入框。

把这些细节放在一起,可以得出一句结论:这是一道误触闸门。它拦的是随手点按,不是身份。会做两位数乘法的人都能让门让路,而它自身不具备任何记忆——答错十次和答错一次,在系统里留下的痕迹完全相同。

三、守卫面普查:六处入口,一个目标

判断一道门是紧还是松,先要看它挂在哪些入口上。把工程扫一遍,触发这道门的位置一共有六处,分布在五个视图文件中。

入口所在位置触发条件门后目标
解锁全部奥德赛地图章节头未购买且未开演示态付费墙
锁定关卡卡奥德赛关卡网格该关非免费且未购买付费墙
实验工具栏 Pro沙盒实验室页未购买且未开演示态付费墙
解锁大师通行证实验详情页该实验不在免费层付费墙
升级按钮家长中心报告页未购买且未开演示态付费墙
升级按钮设置页权益卡未购买且未开演示态付费墙

六处入口,同一个目的地:付费墙。这意味着这道门当前承担的职责是”把花钱这个动作拦一道”,而不是”把内容拦住”。这一点与实现是自洽的:内容锁由商店权益判定与关卡解锁规则负责,门只负责在用户即将付费的那一刻加一道确认。

普查里还发现一处口径差,值得单独写出来。门上的说明文字写着”请解答这道算术题以继续购买或访问外部链接”,而在这份源码里,打开外部链接的调用点数量是零:工程中没有任何一处打开系统浏览器、承载网页视图或发起网络请求的代码,全部源文件里连一个网址字符串都找不到。文案承诺的守卫面大于实现面。这属于需要收敛的一类偏差:要么把文案改回与实际守卫面一致,要么在真的有外链入口时补上守卫。

四、门没有装在哪几条路上

真正需要被认真对待的,是没有被这道门覆盖的四条面。

未受守卫的面触发方式后果
文凭导出与系统分享证书页一键导出 PDF,随后弹出系统分享面板含学生姓名的文档离开设备
学习进度重置设置页一次点击加一个确认弹窗全部星级、徽章与进度清零
教师演示开关设置页开关,或奥德赛首页工具栏按钮解锁判定短路,并隐藏升级入口
家长中心报告底部标签页直接进入学习数据对任何持机者可见

第一条是文凭出口。证书页允许输入学生姓名(默认给出占位名,可修改),页面实时预览证书版面,一键生成 A4 横版文档,内容包含机构名、受证人姓名、成绩摘要与一行凭证编号,随后交给系统分享面板。整个过程没有家长门:导出按钮直接生成并唤起分享面板,用户选择哪个应用去接收,应用不参与也不再知情。这条路径上流动的是真实的本地数据——姓名与成绩,一旦分享完成,它们就离开了设备。如果门的责任范围只覆盖付费,这一条就是最需要补的门外动作。

第二条是学习进度重置。它是破坏性动作,实现上只有一次确认弹窗,没有门。破坏性动作是否需要家长门,取决于产品怎么判断”数据可恢复性”:本地进度没有服务端副本,重置即彻底消失。这里可以明确的是,保护强度与后果强度并不匹配——花钱只被拦了一道,清空全部学习记录反而只需要点两下。

第三条是教师演示开关,它在内容解锁这件事上的位置需要单独讨论,留到下一节。

第四条是家长报告本身。报告页是底部标签之一,直接进入,没有门。对面向家长的功能来说这并非错误设计——报告的目标读者本就是家长;但它意味着”研读学习数据”这件事上没有控制:报告页里的学生姓名、星级统计与能力维度条,对任何拿到设备的人都可见。

把这两节合起来看,可以给出一道比较准确的描述:这道门装在花钱的路上,没有装在数据出门的路上。

判定与出口:门守在购买路径上,出口路径没有门路径一:商店权益本机凭据读取与签名校验未购即挡,购买前先过家长门路径二:教师演示开关一个布尔存于本机偏好设置切换后解锁判定立刻短路解锁判定两条路径在此汇合演示开关不经过门门外的四条出口文凭 PDF:含学生姓名分享面板:交给系统应用进度重置:仅确认弹窗家长报告:标签页直进演示开关:无需任何校验演示态通关与真实学习记录写入同一份进度存储,报告中不作区分门降低的是误触概率;数据的边界由数据不出设备来守

五、一个本地布尔能走到哪里

演示模式的实现是一个布尔量,保存在本机偏好设置中。它的开与关有两个触发点:设置页里的一枚开关,以及奥德赛首页工具栏上的快捷按钮——后者只需一次点按,没有确认,也没有门。

真正需要看的是它在判定中的位置。内容是否可玩由两条路径共同决定:

U=D∨L,Plocked=¬D∧¬F∧¬EU = D \lor L, \qquad P_{\mathrm{locked}} = \lnot D \land \lnot F \land \lnot E

其中 DD 表示演示开关已打开,LL 表示关卡与章节的常规解锁规则成立,FF 表示该关属于免费层,EE 表示商店权益已确认。第一个式子的含义是:只要演示开关打开,解锁判定立刻短路为真,不必再等待其他条件。第二个式子的含义是:当演示开关打开时,任何内容都不会被判为锁定,与之连带的升级入口也随之从界面上消失。

这个设计本身不是缺陷叙事。课堂演示需要让一台设备在教室里把 96 关全部打开,这是一条真实需求,用一个本地开关而不是一组临时代码去满足它,是合理的选择。需要如实写出的,是它带来的两个后果。

后果一,它是内容解锁这件事上最强的一路。商店权益需要走一趟本机凭据读取与签名校验,而演示开关只需要切换一个布尔;从旁路审视,门的六处入口全部服务于付费路径,而这个开关让付费路径整体不再出现——也就是说,家长门最强的那一面,被一个不经门的本地开关绕开了。

后果二,它不留下来源标记。审查显示,演示开关只被视图层读取,数据模型对它一无所知;而在演示态下完成的关卡结算,写入的是与其他所有关卡同一份星级数据。换句话说,同一份进度存储里,演示阶段验证过的关卡与真实学习获得的关卡无法区分,家长报告与文凭所依据的计数会把两者一并算入。这是一处可以修、但需要先明确取向的问题:要么写入来源标记并在报告中分列,要么让演示态数据在展示上有所区别。目前两者都还没有做。

同样要说明,走查启动参数的影响面比演示开关更大:它会让章节解锁、关卡解锁与家长门判定同时恒真,是自动化测试使用的通道,只存在于测试与调试语境,正式分发的构建里不会携带这类参数。

六、无账户场景里,“家长同意”还剩下什么

回到合规本身。未成年人隐私规则的核心义务,是”在收集个人信息之前取得可验证的家长同意”——义务的触发点是收集。这类端侧应用正因为不收集而避开了它:没有账户、没有云端、没有遥测,也就没有需要取证的同意环节。

设置页里有一段面向家长的说明,逐条声明了四项事实:应用纯本地运行,不设远程服务器;不收集、不存储、不传输任何个人身份信息、地理位置与使用分析数据;没有广告与第三方开发工具包;遵循儿童隐私法规与平台儿童类别要求。这四条与静态审查结果一致:全部源文件里没有网络请求调用点,没有网址字符串,第三方依赖为零,商店接口只出现在权益校验这一条路径上。

但”不收集”并不等于”没有数据”。端侧至少存在两类信息:其一是学习进度,包括星级、徽章、连击与总量统计;其二是可以输入的学生姓名。它们都留在设备里,除非用户主动按下导出与分享。这就把问题的重心从入口搬到了出口:既然数据不会自己出门,真正需要守的就是那几处能让数据出门的动作,而这恰好是眼下唯一没有门的环节。

还有一条边界需要写明。离线状态下,“可验证”三个字无法落实:设备不能核验操作者是不是家长,也不能把一次通过转化为一次有法律意义的同意表示;应用既不能证明、也不试图证明答题的人是成年人。门在离线语境里只能是一种降低误触概率的流程设计。替未成年人守住隐私的,不是这道两位数乘法题,而是”不收集”这件事本身。

七、四条可以落地的工程线

把前面的审查结果收拢,可以得到四条改动量不大、方向明确的工程线。

工程线现状建议动作收益
守卫入口归一六处触发点各写一遍使能逻辑集中声明受守卫动作清单,由单一修饰器统一挂载新增入口不会漏挂
出口动作纳入守卫文凭导出与系统分享无门分享前过门,并显式告知文档含姓名与成绩数据出门前有确认
演示态留痕结算写入不区分来源写入时记录来源标记,报告与文凭分列学习证据可解释
自检普查清单依赖人工记忆把打开外链、分享导出、删除类调用点列成清单,改界面后逐项核对口径差不再复现

第一条的意义在于可维护性:六个地方各写一遍条件判断,下一次新增付费入口时漏掉门的概率并不低;把它收敛成统一的挂载方式,漏挂就变成一处集中可见的问题。第二条是把门从购买路径扩展到出口路径,同时补上那句目前缺失的告知。第三条不改变任何玩法,只是让数据自己带上解释能力。第四条是给未来的自己留一份检查表:本文里发现的那处文案与实现不一致,正是靠一次这样的普查才暴露出来的。

八、这道门的能力边界

把前面的分析收成一份清单。

能够做到的:把未成年人随手点进购买流程的概率明显压低;在无网络条件下依靠本机随机数与本地比较完成判定;对自动化测试保持可驱动性;不引入任何权限、第三方依赖与网络请求。

做不到的至少有六条。第一,不能核验身份:会做两位数乘法的人都能通过,题目难度区分的是数学能力,不是年龄与监护关系。第二,不能形成一次可举证的同意:离线环境里没有第三方可以为这次通过作证。第三,不能覆盖全部后果动作:文凭导出与系统分享、进度重置、演示开关都不在守卫面上。第四,不能阻止演示态旁路:一个本机布尔即可让解锁判定短路,而这条路径不经过门。第五,不能区分数据来源:演示态取得的关卡与真实学习记录写在同一份存储里,报告无从分辨。第六,不能自证覆盖完整:门上的文案已经承诺了一个并不存在的守卫面,这提醒我们守卫面需要靠普查来确认,而不是靠文字来宣称。

这份清单不是缺陷目录,而是这类端侧产品在没有服务端可依赖时呈现出的真实边界。门之所以必须由本地代码自己立起来,是因为没有别的地方可以立;而它之所以只需要做到降低误触,是因为真正的隐私保护已经由另一项设计完成了——数据不出设备。把两件事放在一起才是完整的产品说明:一边用离线守住数据的边界,一边在必要的入口上放一道诚实的、能力有限的确认环节。

九、结语

在一款不联网、不注册、不采集的儿童教学应用里,家长门是少数需要与外部规则对齐的界面构件:平台要求它存在,而它掌握的全部信息只是本机生成的一个随机数。它挡不住会做乘法题的孩子,也证明不了坐在设备前面的是谁,更没法替自己覆盖文凭导出、进度重置与本地演示开关这几条旁路。但它也不该被夸大——真正让家长放心的,是这台设备上没有可以被拿走的数据。把门立在购买路径上、把出口动作的告知补齐、把演示态的痕迹标出来,这三件事做完之后,这道两位数乘法题才算站在了它该在的位置:不是安全边界,而是流程里最后一道礼节。

参考文献

[1] U.S. Federal Trade Commission, Children’s Online Privacy Protection Rule (16 CFR Part 312). https://www.ftc.gov/legal-library/browse/rules/childrens-online-privacy-protection-rule-coppa [2] U.S. Federal Trade Commission, Complying with COPPA: Frequently Asked Questions. https://www.ftc.gov/business-guidance/resources/complying-coppa-frequently-asked-questions [3] Apple Inc., App Review Guidelines — 1.3 Kids Category and 5.1 Privacy. https://developer.apple.com/app-store/review/guidelines/ [4] Apple Inc., UIActivityViewController. https://developer.apple.com/documentation/uikit/uiactivityviewcontroller [5] Apple Inc., App privacy details on the App Store. https://developer.apple.com/app-store/app-privacy-details/ [6] UK Information Commissioner’s Office, Age Appropriate Design Code. https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/childrens-information/childrens-code-guidance-and-resources/age-appropriate-design-code/

Share:
Back to Blog