Re: On the unfortunate need for an "age verification" API for legal compliance reasons in some U.S. states
Jean-Baptiste Lallement <[email protected]> Wed, 4 Mar 2026 11:51:24 +0100
| Newsgroups | gmane.linux.debian.devel.general,gmane.linux.xdg.devel,gmane.linux.redhat.fedora.devel,gmane.linux.ubuntu.devel,gmane.linux.debian.devel.legal,gmane.linux.redhat.fedora.legal |
|---|---|
| Message-ID | <CAP9UiMUCvB4DK4ycu9vRQbuQHehe-BJzRTy0HFDZGXhcDNobJg@mail.gmail.com> |
--00000000000089fe41064c309a49 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Since this thread generated quite a bit of discussion, Canonical has published a clarification regarding Ubuntu and the California Digital Age Assurance Act (AB-1043) being discussed here: https://discourse.ubuntu.com/t/ubuntus-response-to-californias-digital-age-= assurance-act-ab-1043/77948 On Sun, Mar 1, 2026 at 8:49=E2=80=AFPM Aaron Rainbolt <[email protected]= > 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", ">=3D 13 and < 16", ">=3D 16 and < 18", and ">=3D 18". It looks l= ike > 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=3D"/org/freedesktop/AgeVerification1"> > <interface name=3D"org.freedesktop.AgeVerification1"> > <method name=3D"SetAge"> > <arg type=3D"s" name=3D"User" direction=3D"in"/> > <arg type=3D"u" name=3D"YearsOfAge" direction=3D"in"/> > </method> > <method name=3D"SetDateOfBirth"> > <arg type=3D"s" name=3D"User" direction=3D"in"/> > <arg type=3D"s" name=3D"Date" direction=3D"in"/> > </method> > <method name=3D'GetAgeBracket'> > <arg type=3D"s" name=3D"User" direction=3D"in"/> > <arg type=3D"u" name=3D"AgeBracket" direction=3D"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=3D2= 02520260AB1043 > [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/ > -- > ubuntu-devel mailing list > [email protected] > Modify settings or unsubscribe at: > https://lists.ubuntu.com/mailman/listinfo/ubuntu-devel > --00000000000089fe41064c309a49 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div dir=3D"ltr"><p class=3D"gmail-isSelectedEnd">Since th= is thread generated quite a bit of discussion, Canonical has published a cl= arification regarding Ubuntu and the California Digital Age Assurance Act (= AB-1043) being discussed here:</p><p><a href=3D"https://discourse.ubuntu.co= m/t/ubuntus-response-to-californias-digital-age-assurance-act-ab-1043/77948= ">https://discourse.ubuntu.com/t/ubuntus-response-to-californias-digital-ag= e-assurance-act-ab-1043/77948</a></p></div><br><div class=3D"gmail_quote gm= ail_quote_container"><div dir=3D"ltr" class=3D"gmail_attr">On Sun, Mar 1, 2= 026 at 8:49=E2=80=AFPM Aaron Rainbolt <<a href=3D"mailto:arraybolt3@gmai= l.com">[email protected]</a>> wrote:<br></div><blockquote class=3D"gm= ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,= 204,204);padding-left:1ex">Given that this is related to legal stuff, I sho= uld preface this by<br> saying I am not a lawyer.<br> <br> Recently, a new law was passed in California that requires OS vendors<br> to provide some limited info about a user's age via an API that<br> application distribution websites and application stores can use. [1]<br> Colorado seems to be working on a similar law. [2] The law will go into<br> effect January 1, 2027, it is no longer a draft. I do quite a bit of<br> work with an OS vendor (working with the Kicksecure [3] and Whonix [4]<br> projects), and we aren't particularly interested in blocking everyone<b= r> in California and Colorado from using our OSes, so we're currently<br> looking into how to implement an API that will comply with the laws<br> while also not being a privacy disaster. Given that other distributions<br> are also investigating what to do with this, and the law requires us to<br> make a "good faith effort to comply with [the] title, taking into<br> consideration available technology", I figured it would be a good idea= <br> to bring the issue here.<br> <br> At its core, the law seems to require that an "operating system"<= br> (I'm guessing this would correspond to a Linux distribution, not an OS<= br> kernel or userland) request the user's age or date of birth at "ac= count<br> setup". The OS is also expected to allow users to set the user's a= ge if<br> they didn't already provide it (because the OS was installed before the= <br> law went into effect), and it needs to provide an API somewhere so that<br> app stores and application distribution websites can ask the OS "what<= br> age bracket does this user fall into?" Four age brackets are defined,<= br> "< 13", ">=3D 13 and < 16", ">=3D 16 a= nd < 18", and ">=3D 18". It looks like<br> the API also needs to not provide more information than just the age<br> bracket data. A bunch of stuff is left unclear (how to handle servers<br> and other CLI-only installs, how to handle VMs, whether the law is even<br> applicable if the primary user is over 18 since the law ridiculously<br> defines a user as "a child" while also defining "a child&quo= t; as anyone<br> under the age of 18, etc.), but that's what we're given to deal wit= h.<br> <br> The most intuitive place to put this functionality would be, IMO,<br> AccountsService. The main issue with that is that stable-release<br> distributions, and distributions based upon them, would be faced with<br> the issue of how to get an updated version of AccountsService integrated<br= > into their software repositories, or how to backport the appropriate<br> code. The law goes into effect on January 1, 2027, Debian Bookworm is<br> going to be supported by ELTS until July 30, 2033, and we don't yet<br> know if Debian will care enough about California's laws to want to<br> backport a new feature in AccountsService into Debian Bookworm (or even<br> Trixie). Distributions based on Debian (such as Kicksecure and Whonix)<br> may still want to comply with the law though, so something using<br> AccountsService-specific APIs would be frustrating. Requiring a whole<br> separate daemon for the foreseeable future just for an age verification<br> API would also be annoying.<br> <br> Another place the functionality could go is xdg-desktop-portal. This<br> one is a bit non-ideal for a couple of reasons; for one, the easiest<br> place to put the call would be in the Account portal, which returns<br> more information than the account's age bracket. This could potentially= <br> be considered non-compliant with the law, as it states that the<br> operating system shall "[s]end only the minimum amount of information<= br> necessary to comply with this title". This also comes with the<br> backporting disadvantages of an AccountsService-based implementation.<br> <br> For this reason, I'd like to propose a "hybrid" approach; int= roduce a<br> new standard D-Bus interface, `org.freedesktop.AgeVerification1`, that<br> can be implemented by arbitrary applications as a distro sees fit.<br> AccountsService could implement this API so that newer versions<br> of distros will get the relevant features for free, while distros with<br> an AccountsService too old to contain the feature can implement it<br> themselves as a stop-gap solution.<br> <br> Taking inspiration from the File Manager D-Bus interface [5], I think<br> something like the following might work:<br> <br> =C2=A0 =C2=A0 <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Obje= ct Introspection 1.0//EN"<br> =C2=A0 =C2=A0 =C2=A0"<a href=3D"http://www.freedesktop.org/standards/d= bus/1.0/introspect.dtd" rel=3D"noreferrer" target=3D"_blank">http://www.fre= edesktop.org/standards/dbus/1.0/introspect.dtd</a>"><br> =C2=A0 =C2=A0 <node name=3D"/org/freedesktop/AgeVerification1"= ><br> =C2=A0 =C2=A0 =C2=A0 <interface name=3D"org.freedesktop.AgeVerifica= tion1"><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 <method name=3D"SetAge"><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <arg type=3D"s" name=3D&quo= t;User" direction=3D"in"/><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <arg type=3D"u" name=3D&quo= t;YearsOfAge" direction=3D"in"/><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 </method><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 <method name=3D"SetDateOfBirth">= ;<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <arg type=3D"s" name=3D&quo= t;User" direction=3D"in"/><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <arg type=3D"s" name=3D&quo= t;Date" direction=3D"in"/><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 </method><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 <method name=3D'GetAgeBracket'><b= r> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <arg type=3D"s" name=3D&quo= t;User" direction=3D"in"/><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <arg type=3D"u" name=3D&quo= t;AgeBracket" direction=3D"out"/><br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 </method><br> =C2=A0 =C2=A0 =C2=A0 </interface><br> =C2=A0 =C2=A0 </node><br> <br> * The 'User' argument would, in all instances, be expected to be th= e<br> =C2=A0 UNIX account username of the user in question. This user account mus= t<br> =C2=A0 not be a system account (i.e. its UID must fall between UID_MIN and<= br> =C2=A0 UID_MAX as defined by /etc/login.defs). If a user is specified that<= br> =C2=A0 does not exist or whose UID is out of range, these methods will<br> =C2=A0 return the error 'org.freedesktop.AgeVerification1.Error.NoSuchU= ser'.<br> =C2=A0 If the specified user is not the same as the user making the method<= br> =C2=A0 call, and the user making the method call is not root, these methods= <br> =C2=A0 will return the error<br> =C2=A0 'org.freedesktop.AgeVerification1.Error.PermissionDenied'.<b= r> * The 'YearsOfAge' argument of the 'SetAge' method should b= e an<br> =C2=A0 unsigned integer specifying the age of the user in years at the time= <br> =C2=A0 of the method call. (The law specifically allows providing simply an= <br> =C2=A0 age value rather than a birth date if desired.)<br> * The 'Date' argument of the 'SetDateOfBirth' method should= be a string<br> =C2=A0 in ISO8601 format (i.e. YYYY-MM-DD) indicating the day on which the<= br> =C2=A0 user was born. If the argument is invalid, the method will return th= e<br> =C2=A0 error 'org.freedesktop.AgeVerification1.Error.InvalidDate'.<= br> * The 'AgeBracket' output argument of the 'GetAgeBracket' m= ethod will be<br> =C2=A0 an unsigned integer between 1 and 4 inclusive, where 1 indicates tha= t<br> =C2=A0 the user is under 13 years old, 2 indicates that the user is at leas= t<br> =C2=A0 13 and under 16 years old, 3 indicates that the user is at least 16<= br> =C2=A0 and under 18 years old, and 4 indicates that the user is 18 years ol= d<br> =C2=A0 or older. If no age has been configured for the user yet, the method= <br> =C2=A0 will return the error<br> =C2=A0 'org.freedesktop.AgeVerification1.Error.AgeUndefined'.<br> <br> I propose that the exact way in which age information is stored by the<br> daemon should be left implementation-defined. For Kicksecure, the way<br> we implement it will almost certainly store only the age bracket and<br> require users to explicitly reconfigure their age once they are old<br> enough to move from one age bracket to another. Other implementations<br> may choose to store the date of birth or the age and date on which the<br> age was set so that they can automatically update the age bracket as<br> time passes. This interface will be provided *on the system bus* (NOT<br> the session bus!), and the D-Bus service that provides these services<br> should run as root. The file containing the user-to-age mappings should<br> be owned by root and should not be world-readable, to prevent leaking<br> the user's specific age to malicious applications.<br> <br> Some things I did think about when writing the above but ultimately<br> decided to not propose:<br> <br> * Detailed permission gating for the 'GetAgeBracket' method. The on= ly<br> =C2=A0 reason to do this would be for additional privacy, and<br> =C2=A0 privacy-conscious users can simply lie about their age or the age of= <br> =C2=A0 the intended user. There isn't anything in the law (that I can t= ell)<br> =C2=A0 that prevents the user from just saying "I'm 18" when = the prompt<br> =C2=A0 appears and going with it. This would also be really difficult to<br= > =C2=A0 implement outside of the context of xdg-desktop-portal, and would<br= > =C2=A0 probably only work with sandboxed apps if it was implemented that wa= y.<br> * UX for actually requesting the age from the user. IMO this is out of<br> =C2=A0 scope for FreeDesktop; individual distros should see to it that they= <br> =C2=A0 prompt for the user's age or birth date at "account setup&q= uot; (whatever<br> =C2=A0 that happens to be defined as for the distro in question), nudge the= <br> =C2=A0 user to provide the information later on for existing installations,= <br> =C2=A0 etc. Furthermore, this mechanism needs to work even on CLI-only<br> =C2=A0 installs and maybe even on server installs, depending on how one<br> =C2=A0 defines "general purpose computing device" (as specified b= y the law<br> =C2=A0 in question), so defining any specific UX is likely infeasible. (If<= br> =C2=A0 this is required on servers, end-users will probably want to<br> =C2=A0 auto-provision the age information somehow, and specifying how to do= <br> =C2=A0 that in a distribution-agnostic way is impossible given that Ubuntu<= br> =C2=A0 uses cloud-init, Fedora uses Kickstart and Ignition, etc.)<br> * Omitting the 'SetDateOfBirth' method. It can be lived without<br> =C2=A0 legally, but without the method, it becomes difficult for software<b= r> =C2=A0 that already records the user's date of birth to accurately impl= ement<br> =C2=A0 automatic age bracket adjustment as time passes. This isn't a fe= ature<br> =C2=A0 Kicksecure would use, but it's a feature some projects might be<= br> =C2=A0 interested in.<br> <br> Thanks for taking a look at this.<br> <br> --<br> Aaron<br> <br> [1] <a href=3D"https://leginfo.legislature.ca.gov/faces/billTextClient.xhtm= l?bill_id=3D202520260AB1043" rel=3D"noreferrer" target=3D"_blank">https://l= eginfo.legislature.ca.gov/faces/billTextClient.xhtml?bill_id=3D202520260AB1= 043</a><br> [2] <a href=3D"https://leg.colorado.gov/bill_files/110990/download" rel=3D"= noreferrer" target=3D"_blank">https://leg.colorado.gov/bill_files/110990/do= wnload</a><br> [3] <a href=3D"https://www.kicksecure.com/" rel=3D"noreferrer" target=3D"_b= lank">https://www.kicksecure.com/</a><br> [4] <a href=3D"https://www.whonix.org/" rel=3D"noreferrer" target=3D"_blank= ">https://www.whonix.org/</a><br> [5] <a href=3D"https://www.freedesktop.org/wiki/Specifications/file-manager= -interface/" rel=3D"noreferrer" target=3D"_blank">https://www.freedesktop.o= rg/wiki/Specifications/file-manager-interface/</a><br> -- <br> ubuntu-devel mailing list<br> <a href=3D"mailto:[email protected]" target=3D"_blank">ubuntu-d= [email protected]</a><br> Modify settings or unsubscribe at: <a href=3D"https://lists.ubuntu.com/mail= man/listinfo/ubuntu-devel" rel=3D"noreferrer" target=3D"_blank">https://lis= ts.ubuntu.com/mailman/listinfo/ubuntu-devel</a><br> </blockquote></div></div> --00000000000089fe41064c309a49--