Re: On the unfortunate need for an "age verification" API for legal compliance reasons in some U.S. states
Danielle Foré <[email protected]> Mon, 2 Mar 2026 10:36:52 -0800
| Newsgroups | gmane.linux.xdg.devel,gmane.linux.debian.devel.general,gmane.linux.redhat.fedora.devel,gmane.linux.ubuntu.devel,gmane.linux.debian.devel.legal,gmane.linux.redhat.fedora.legal |
|---|---|
| Message-ID | <CADpqsky71cqskqrytiMJahyMd3cQa5_gFtq+6uvfvQtEmYzZ1A@mail.gmail.com> |
Hey Aaron et al, I'm digging into this a bit more this morning and I found something really interesting in Apple's implementation. It seems that what they do is that apps will send an array containing 3 age gates and their API responds with two ints, a lower bound and upper bound. The values of the lower and upper bounds will be either -1 or the value of one of the gates you sent. Lower is the lowest age gate they exceed and upper is the highest age gate they are below. For example: I send the api an array of [9, 13, 16]. If the API responds [9, 16], the child is older than 9 but under 16. If the API responds [-1, 16], the child is under 9 If the API responds [16, -1], the child is over 16. Apps can also send -1 for the last two ints, which seems to help with sending only the minimum information. For example: I send the api an array of [16, -1, -1], the api responds with [-1, 16] to let me know the child is under 16 or [16, -1] to let me know the child is over 16. Their docs also say the system might respond with different values based on regulations in the region. So for example I send the api an array of [15, 16, 17] because I'm doing something nefarious, the api responds with either [13, 16] or [16, 18] to make sure it's returning a range and not an age. It seems pretty clever. They also have provisions for declining to share based on region etc. Full documentation here: https://developer.apple.com/documentation/declaredagerange/ On Sun, Mar 1, 2026 at 2:10 PM Aaron Rainbolt <[email protected]> wrote: > On Sun, 1 Mar 2026 14:02:56 -0800 > Jamie Null <[email protected]> wrote: > > > On 2026-03-01 12:42, Aaron Rainbolt wrote: > > > On Sun, 1 Mar 2026 15:12:09 -0500 > > > "Vincent F. Heuser Jr." <[email protected]> wrote: > > > > > >> On 2026/03/01 14:48 PM, Aaron Rainbolt wrote: > > >>> Given that this is related to legal stuff, I should preface this > > >>> by saying I am not a lawyer. > > >>> > > >>> Recently, a new law was passed in California that requires OS > > >>> vendors to provide some limited info about a user's age via an API > > >>> that application distribution websites and application stores can > > >>> use. [1] Colorado seems to be working on a similar law. [2] The > > >>> law will go into effect January 1, 2027, it is no longer a draft. > > >>> I do quite a bit of work with an OS vendor (working with the > > >>> Kicksecure [3] and Whonix [4] projects), and we aren't > > >>> particularly interested in blocking everyone in California and > > >>> Colorado from using our OSes, so we're currently looking into how > > >>> to implement an API that will comply with the laws while also not > > >>> being a privacy disaster. Given that other distributions are also > > >>> investigating what to do with this, and the law requires us to > > >>> make a "good faith effort to comply with [the] title, taking into > > >>> consideration available technology", I figured it would be a good > > >>> idea to bring the issue here. > > >>> > > >>> At its core, the law seems to require that an "operating system" > > >>> (I'm guessing this would correspond to a Linux distribution, not > > >>> an OS kernel or userland) request the user's age or date of birth > > >>> at "account setup". The OS is also expected to allow users to set > > >>> the user's age if they didn't already provide it (because the OS > > >>> was installed before the law went into effect), and it needs to > > >>> provide an API somewhere so that app stores and application > > >>> distribution websites can ask the OS "what age bracket does this > > >>> user fall into?" Four age brackets are defined, "< 13", ">= 13 > > >>> and < 16", ">= 16 and < 18", and ">= 18". It looks like the API > > >>> also needs to not provide more information than just the age > > >>> bracket data. A bunch of stuff is left unclear (how to handle > > >>> servers and other CLI-only installs, how to handle VMs, whether > > >>> the law is even applicable if the primary user is over 18 since > > >>> the law ridiculously defines a user as "a child" while also > > >>> defining "a child" as anyone under the age of 18, etc.), but > > >>> that's what we're given to deal with. > > >>> > > >>> The most intuitive place to put this functionality would be, IMO, > > >>> AccountsService. The main issue with that is that stable-release > > >>> distributions, and distributions based upon them, would be faced > > >>> with the issue of how to get an updated version of AccountsService > > >>> integrated into their software repositories, or how to backport > > >>> the appropriate code. The law goes into effect on January 1, 2027, > > >>> Debian Bookworm is going to be supported by ELTS until July 30, > > >>> 2033, and we don't yet know if Debian will care enough about > > >>> California's laws to want to backport a new feature in > > >>> AccountsService into Debian Bookworm (or even Trixie). > > >>> Distributions based on Debian (such as Kicksecure and Whonix) may > > >>> still want to comply with the law though, so something using > > >>> AccountsService-specific APIs would be frustrating. Requiring a > > >>> whole separate daemon for the foreseeable future just for an age > > >>> verification API would also be annoying. > > >>> > > >>> Another place the functionality could go is xdg-desktop-portal. > > >>> This one is a bit non-ideal for a couple of reasons; for one, the > > >>> easiest place to put the call would be in the Account portal, > > >>> which returns more information than the account's age bracket. > > >>> This could potentially be considered non-compliant with the law, > > >>> as it states that the operating system shall "[s]end only the > > >>> minimum amount of information necessary to comply with this > > >>> title". This also comes with the backporting disadvantages of an > > >>> AccountsService-based implementation. > > >>> > > >>> For this reason, I'd like to propose a "hybrid" approach; > > >>> introduce a new standard D-Bus interface, > > >>> `org.freedesktop.AgeVerification1`, that can be implemented by > > >>> arbitrary applications as a distro sees fit. AccountsService > > >>> could implement this API so that newer versions of distros will > > >>> get the relevant features for free, while distros with an > > >>> AccountsService too old to contain the feature can implement it > > >>> themselves as a stop-gap solution. > > >>> > > >>> Taking inspiration from the File Manager D-Bus interface [5], I > > >>> think something like the following might work: > > >>> > > >>> <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object > > >>> Introspection 1.0//EN" > > >>> "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> > > >>> <node name="/org/freedesktop/AgeVerification1"> <interface > > >>> name="org.freedesktop.AgeVerification1"> <method name="SetAge"> > > >>> <arg type="s" name="User" direction="in"/> > > >>> <arg type="u" name="YearsOfAge" direction="in"/> > > >>> </method> > > >>> <method name="SetDateOfBirth"> > > >>> <arg type="s" name="User" direction="in"/> > > >>> <arg type="s" name="Date" direction="in"/> > > >>> </method> > > >>> <method name='GetAgeBracket'> > > >>> <arg type="s" name="User" direction="in"/> > > >>> <arg type="u" name="AgeBracket" direction="out"/> > > >>> </method> > > >>> </interface> > > >>> </node> > > >>> > > >>> * The 'User' argument would, in all instances, be expected to be > > >>> the UNIX account username of the user in question. This user > > >>> account must not be a system account (i.e. its UID must fall > > >>> between UID_MIN and UID_MAX as defined by /etc/login.defs). If a > > >>> user is specified that does not exist or whose UID is out of > > >>> range, these methods will return the error > > >>> 'org.freedesktop.AgeVerification1.Error.NoSuchUser'. If the > > >>> specified user is not the same as the user making the method call, > > >>> and the user making the method call is not root, these methods > > >>> will return the error > > >>> 'org.freedesktop.AgeVerification1.Error.PermissionDenied'. > > >>> * The 'YearsOfAge' argument of the 'SetAge' method should be an > > >>> unsigned integer specifying the age of the user in years at > > >>> the time of the method call. (The law specifically allows > > >>> providing simply an age value rather than a birth date if > > >>> desired.) > > >>> * The 'Date' argument of the 'SetDateOfBirth' method should be a > > >>> string in ISO8601 format (i.e. YYYY-MM-DD) indicating the day on > > >>> which the user was born. If the argument is invalid, the method > > >>> will return the error > > >>> 'org.freedesktop.AgeVerification1.Error.InvalidDate'. > > >>> * The 'AgeBracket' output argument of the 'GetAgeBracket' method > > >>> will be an unsigned integer between 1 and 4 inclusive, where 1 > > >>> indicates that the user is under 13 years old, 2 indicates that > > >>> the user is at least 13 and under 16 years old, 3 indicates that > > >>> the user is at least 16 and under 18 years old, and 4 indicates > > >>> that the user is 18 years old or older. If no age has been > > >>> configured for the user yet, the method will return the error > > >>> 'org.freedesktop.AgeVerification1.Error.AgeUndefined'. > > >>> > > >>> I propose that the exact way in which age information is stored by > > >>> the daemon should be left implementation-defined. For Kicksecure, > > >>> the way we implement it will almost certainly store only the age > > >>> bracket and require users to explicitly reconfigure their age once > > >>> they are old enough to move from one age bracket to another. Other > > >>> implementations may choose to store the date of birth or the age > > >>> and date on which the age was set so that they can automatically > > >>> update the age bracket as time passes. This interface will be > > >>> provided *on the system bus* (NOT the session bus!), and the D-Bus > > >>> service that provides these services should run as root. The file > > >>> containing the user-to-age mappings should be owned by root and > > >>> should not be world-readable, to prevent leaking the user's > > >>> specific age to malicious applications. > > >>> > > >>> Some things I did think about when writing the above but > > >>> ultimately decided to not propose: > > >>> > > >>> * Detailed permission gating for the 'GetAgeBracket' method. The > > >>> only reason to do this would be for additional privacy, and > > >>> privacy-conscious users can simply lie about their age or the > > >>> age of the intended user. There isn't anything in the law (that I > > >>> can tell) that prevents the user from just saying "I'm 18" when > > >>> the prompt appears and going with it. This would also be really > > >>> difficult to implement outside of the context of > > >>> xdg-desktop-portal, and would probably only work with sandboxed > > >>> apps if it was implemented that way. > > >>> * UX for actually requesting the age from the user. IMO this is > > >>> out of scope for FreeDesktop; individual distros should see to it > > >>> that they prompt for the user's age or birth date at "account > > >>> setup" (whatever that happens to be defined as for the distro in > > >>> question), nudge the user to provide the information later on for > > >>> existing installations, etc. Furthermore, this mechanism needs to > > >>> work even on CLI-only installs and maybe even on server installs, > > >>> depending on how one defines "general purpose computing device" > > >>> (as specified by the law in question), so defining any specific > > >>> UX is likely infeasible. (If this is required on servers, > > >>> end-users will probably want to auto-provision the age > > >>> information somehow, and specifying how to do that in a > > >>> distribution-agnostic way is impossible given that Ubuntu uses > > >>> cloud-init, Fedora uses Kickstart and Ignition, etc.) > > >>> * Omitting the 'SetDateOfBirth' method. It can be lived without > > >>> legally, but without the method, it becomes difficult for > > >>> software that already records the user's date of birth to > > >>> accurately implement automatic age bracket adjustment as time > > >>> passes. This isn't a feature Kicksecure would use, but it's a > > >>> feature some projects might be interested in. > > >>> > > >>> Thanks for taking a look at this. > > >>> > > >>> -- > > >>> Aaron > > >>> > > >>> [1] > > >>> > https://leginfo.legislature.ca.gov/faces/billTextClient.xhtml?bill_id=202520260AB1043 > > >>> [2] https://leg.colorado.gov/bill_files/110990/download [3] > > >>> https://www.kicksecure.com/ [4] https://www.whonix.org/ > > >>> [5] > > >>> > https://www.freedesktop.org/wiki/Specifications/file-manager-interface/ > > >>> > > >> > > >> By definition, not a Debian or Ubuntu problem: > > >> https://www.merriam-webster.com/dictionary/vendor > > > > > > I may have been incorrectly imprecise; the law linked says that "an > > > operating system provider shall" do the things needed to comply with > > > the title, and defines an operating system provider as "a person or > > > entity that develops, licenses, or controls the operating system > > > software on a computer, mobile device, or any other general purpose > > > computing device." "Vendor" is a term I mistakenly used, as far as I > > > can tell the law does not exclude operating systems that are offered > > > for free. Again though, as I stated, I am not a lawyer, so perhaps > > > I'm misunderstanding the meaning of the definition of "operating > > > system provider". > > > > > > -- > > > Aaron > > > > Is there a reason this cannot be implemented as a separate package > > which can be selected through the installer? > > Other than ease of integration, not to my awareness. > > > The issue with building it into existing components is that while an > > "age verification" API might be required in some jurisdictions, there > > are others where providing this API could run afoul of privacy laws > > or is otherwise legally prohibited. Furthermore, should more > > jurisdictions decide to enact poorly-considered "age verification" > > laws with varying requirements as to what is disclosed, it would be > > easier to accommodate those jurisdictions' requirements this way. > > Good point. Maybe integrating this into AccountsService isn't a good > idea, and having a standardized API that can have arbitrary > implementations is a better choice. Maybe another error, > 'org.freedesktop.AgeVerification1.Error.NotApplicable' should be added > to the proposal too. > > -- > Aaron >