Re: On the unfortunate need for an "age verification" API for legal compliance reasons in some U.S. states
Adenix NPSP <[email protected]> Mon, 16 Mar 2026 18:42:34 -0500
| Newsgroups | gmane.linux.debian.devel.legal |
|---|---|
| Message-ID | <CAKiotKzKfL_=tvL_bVO3cjKoyZihDoD+fuUmC-uTi2_AHJffsQ@mail.gmail.com> |
--000000000000860887064d2cc6bd Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hopefully, the age API can be removed or disabled. On Mon, Mar 16, 2026, 6:31=E2=80=AFPM Aaron Rainbolt <[email protected]>= wrote: > For those who have been following the discussion, it may be useful to > know that Kicksecure and Whonix currently "are unlikely to implement an > age API." [1] The D-Bus interface proposed here probably isn't how this > kind of an API would ultimately work (lots of technical issues were > pointed out with it in the discussion), and it looks like it may not be > legally necessary to implement it, depending on how things go from > here. If an age API does end up becoming a thing in the future, it will > probably be based around xdg-desktop-portal [2]. > > [1] https://www.kicksecure.com/wiki/Age-api#status > [2] https://github.com/flatpak/xdg-desktop-portal/pull/1922 > > -- > Aaron > > On Sun, 1 Mar 2026 14:48:00 -0500 > 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 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=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/ > > --000000000000860887064d2cc6bd Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"auto">Hopefully, the age API can be removed or disabled.</div><= br><div class=3D"gmail_quote gmail_quote_container"><div dir=3D"ltr" class= =3D"gmail_attr">On Mon, Mar 16, 2026, 6:31=E2=80=AFPM Aaron Rainbolt <<a= href=3D"mailto:[email protected]">[email protected]</a>> wrote:<b= r></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border= -left:1px #ccc solid;padding-left:1ex">For those who have been following th= e discussion, it may be useful to<br> know that Kicksecure and Whonix currently "are unlikely to implement a= n<br> age API." [1] The D-Bus interface proposed here probably isn't how= this<br> kind of an API would ultimately work (lots of technical issues were<br> pointed out with it in the discussion), and it looks like it may not be<br> legally necessary to implement it, depending on how things go from<br> here. If an age API does end up becoming a thing in the future, it will<br> probably be based around xdg-desktop-portal [2].<br> <br> [1] <a href=3D"https://www.kicksecure.com/wiki/Age-api#status" rel=3D"noref= errer noreferrer" target=3D"_blank">https://www.kicksecure.com/wiki/Age-api= #status</a><br> [2] <a href=3D"https://github.com/flatpak/xdg-desktop-portal/pull/1922" rel= =3D"noreferrer noreferrer" target=3D"_blank">https://github.com/flatpak/xdg= -desktop-portal/pull/1922</a><br> <br> --<br> Aaron<br> <br> On Sun, 1 Mar 2026 14:48:00 -0500<br> Aaron Rainbolt <<a href=3D"mailto:[email protected]" target=3D"_blank= " rel=3D"noreferrer">[email protected]</a>> wrote:<br> <br> > Given that this is related to legal stuff, I should 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<br> > into effect January 1, 2027, it is no longer a draft. I do quite a<br> > bit of work with an OS vendor (working with the Kicksecure [3] and<br> > Whonix [4] projects), and we aren't particularly interested in<br> > blocking everyone in California and Colorado from using our OSes, so<b= r> > we're currently looking into how to implement an API that will com= ply<br> > with the laws while also not being a privacy disaster. Given that<br> > other distributions are also investigating what to do with this, and<b= r> > the law requires us to make a "good faith effort to comply with [= the]<br> > title, taking into consideration available technology", I figured= it<br> > would be a good idea to bring the issue here.<br> > <br> > At its core, the law seems to require that an "operating system&q= uot;<br> > (I'm guessing this would correspond to a Linux distribution, not a= n OS<br> > kernel or userland) request the user's age or date of birth at<br> > "account setup". The OS is also expected to allow users to s= et the<br> > user's age if they didn't already provide it (because the OS w= as<br> > installed before the law went into effect), and it needs to provide<br= > > an API somewhere so that app stores and application distribution<br> > websites can ask the OS "what age bracket does this user fall int= o?"<br> > Four age brackets are defined, "< 13", ">=3D 13 a= nd < 16", ">=3D 16 and <<br> > 18", and ">=3D 18". It looks like the API also needs= to not provide<br> > more information than just the age bracket data. A bunch of stuff is<b= r> > left unclear (how to handle servers and other CLI-only installs, how<b= r> > to handle VMs, whether the law is even applicable if the primary user<= br> > is over 18 since the law ridiculously defines a user as "a child&= quot;<br> > while also defining "a child" as anyone under the age of 18,= etc.),<br> > but that's what we're given to deal with.<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<br> > integrated into their software repositories, or how to backport the<br= > > appropriate code. The law goes into effect on January 1, 2027, Debian<= br> > Bookworm is going to be supported by ELTS until July 30, 2033, and we<= br> > don't yet know if Debian will care enough about California's l= aws to<br> > want to backport a new feature in AccountsService into Debian<br> > Bookworm (or even Trixie). Distributions based on Debian (such as<br> > Kicksecure and Whonix) may still want to comply with the law though,<b= r> > so something using AccountsService-specific APIs would be<br> > frustrating. Requiring a whole separate daemon for the foreseeable<br> > future just for an age verification API would also be annoying.<br> > <br> > Another place the functionality could go is xdg-desktop-portal. This<b= r> > one is a bit non-ideal for a couple of reasons; for one, the easiest<b= r> > place to put the call would be in the Account portal, which returns<br= > > more information than the account's age bracket. This could<br> > potentially be considered non-compliant with the law, as it states<br> > that the operating system shall "[s]end only the minimum amount o= f<br> > information necessary to comply with this title". This also comes= <br> > with the backporting disadvantages of an AccountsService-based<br> > implementation.<br> > <br> > For this reason, I'd like to propose a "hybrid" approach= ; introduce 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 =C2=A0<!DOCTYPE node PUBLIC "-//freedesktop//DTD = D-BUS Object<br> > Introspection 1.0//EN"<br> > "<a href=3D"http://www.freedesktop.org/standards/dbus/1.0/introsp= ect.dtd" rel=3D"noreferrer noreferrer" target=3D"_blank">http://www.freedes= ktop.org/standards/dbus/1.0/introspect.dtd</a>"> <node<br> > name=3D"/org/freedesktop/AgeVerification1"> <interface= <br> > name=3D"org.freedesktop.AgeVerification1"> <method nam= e=3D"SetAge"><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<arg type=3D"s" n= ame=3D"User" direction=3D"in"/><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<arg type=3D"u" n= ame=3D"YearsOfAge" direction=3D"in"/><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</method><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<method name=3D"SetDateOfBirt= h"><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<arg type=3D"s" n= ame=3D"User" direction=3D"in"/><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<arg type=3D"s" n= ame=3D"Date" direction=3D"in"/><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</method><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<method name=3D'GetAgeBracket&= #39;><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<arg type=3D"s" n= ame=3D"User" direction=3D"in"/><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0<arg type=3D"u" n= ame=3D"AgeBracket" direction=3D"out"/><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</method><br> >=C2=A0 =C2=A0 =C2=A0 =C2=A0</interface><br> >=C2=A0 =C2=A0 =C2=A0</node><br> > <br> > * The 'User' argument would, in all instances, be expected to = be the<br> >=C2=A0 =C2=A0UNIX account username of the user in question. This user a= ccount<br> > must not be a system account (i.e. its UID must fall between UID_MIN<b= r> > and UID_MAX as defined by /etc/login.defs). If a user is specified<br> > that does not exist or whose UID is out of range, these methods will<b= r> >=C2=A0 =C2=A0return the error<br> > 'org.freedesktop.AgeVerification1.Error.NoSuchUser'. If the sp= ecified<br> > user is not the same as the user making the method call, and the user<= br> > making the method call is not root, these methods will return the<br> > error 'org.freedesktop.AgeVerification1.Error.PermissionDenied'= ;.<br> > * The 'YearsOfAge' argument of the 'SetAge' method sho= uld be an<br> >=C2=A0 =C2=A0unsigned integer specifying the age of the user in years a= t the time<br> >=C2=A0 =C2=A0of the method call. (The law specifically allows providing= simply an<br> >=C2=A0 =C2=A0age value rather than a birth date if desired.)<br> > * The 'Date' argument of the 'SetDateOfBirth' method s= hould be a<br> > string in ISO8601 format (i.e. YYYY-MM-DD) indicating the day on<br> > which the user was born. If the argument is invalid, the method will<b= r> > return the error 'org.freedesktop.AgeVerification1.Error.InvalidDa= te'.<br> > * The 'AgeBracket' output argument of the 'GetAgeBracket&#= 39; method will<br> > be an unsigned integer between 1 and 4 inclusive, where 1 indicates<br= > > that the user is under 13 years old, 2 indicates that the user is at<b= r> > least 13 and under 16 years old, 3 indicates that the user is at<br> > least 16 and under 18 years old, and 4 indicates that the user is 18<b= r> > years old or older. If no age has been configured for the user yet,<br= > > the method will return the error<br> >=C2=A0 =C2=A0'org.freedesktop.AgeVerification1.Error.AgeUndefined&#= 39;.<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<b= r> > 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<b= r> > 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<br> > should be owned by root and should not be world-readable, to prevent<b= r> > leaking 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. T= he only<br> >=C2=A0 =C2=A0reason to do this would be for additional privacy, and<br> >=C2=A0 =C2=A0privacy-conscious users can simply lie about their age or = the age of<br> >=C2=A0 =C2=A0the intended user. There isn't anything in the law (th= at I can tell)<br> >=C2=A0 =C2=A0that prevents the user from just saying "I'm 18&q= uot; when the prompt<br> >=C2=A0 =C2=A0appears and going with it. This would also be really diffi= cult to<br> >=C2=A0 =C2=A0implement outside of the context of xdg-desktop-portal, an= d would<br> >=C2=A0 =C2=A0probably only work with sandboxed apps if it was implement= ed that<br> > way.<br> > * UX for actually requesting the age from the user. IMO this is out of= <br> >=C2=A0 =C2=A0scope for FreeDesktop; individual distros should see to it= that they<br> >=C2=A0 =C2=A0prompt for the user's age or birth date at "accou= nt setup" (whatever<br> >=C2=A0 =C2=A0that happens to be defined as for the distro in question),= nudge the<br> >=C2=A0 =C2=A0user to provide the information later on for existing inst= allations,<br> >=C2=A0 =C2=A0etc. Furthermore, this mechanism needs to work even on CLI= -only<br> >=C2=A0 =C2=A0installs and maybe even on server installs, depending on h= ow one<br> >=C2=A0 =C2=A0defines "general purpose computing device" (as s= pecified by the law<br> >=C2=A0 =C2=A0in question), so defining any specific UX is likely infeas= ible. (If<br> >=C2=A0 =C2=A0this is required on servers, end-users will probably want = to<br> >=C2=A0 =C2=A0auto-provision the age information somehow, and specifying= how to do<br> >=C2=A0 =C2=A0that in a distribution-agnostic way is impossible given th= at Ubuntu<br> >=C2=A0 =C2=A0uses cloud-init, Fedora uses Kickstart and Ignition, etc.)= <br> > * Omitting the 'SetDateOfBirth' method. It can be lived withou= t<br> >=C2=A0 =C2=A0legally, but without the method, it becomes difficult for = software<br> >=C2=A0 =C2=A0that already records the user's date of birth to accur= ately<br> > implement automatic age bracket adjustment as time passes. This isn= 9;t<br> > a feature Kicksecure would use, but it's a feature some projects<b= r> > might be interested in.<br> > <br> > Thanks for taking a look at this.<br> > <br> > --<br> > Aaron<br> > <br> > [1]<br> > <a href=3D"https://leginfo.legislature.ca.gov/faces/billTextClient.xht= ml?bill_id=3D202520260AB1043" rel=3D"noreferrer noreferrer" target=3D"_blan= k">https://leginfo.legislature.ca.gov/faces/billTextClient.xhtml?bill_id=3D= 202520260AB1043</a><br> > [2] <a href=3D"https://leg.colorado.gov/bill_files/110990/download" re= l=3D"noreferrer noreferrer" target=3D"_blank">https://leg.colorado.gov/bill= _files/110990/download</a> [3]<br> > <a href=3D"https://www.kicksecure.com/" rel=3D"noreferrer noreferrer" = target=3D"_blank">https://www.kicksecure.com/</a> [4] <a href=3D"https://ww= w.whonix.org/" rel=3D"noreferrer noreferrer" target=3D"_blank">https://www.= whonix.org/</a><br> > [5]<br> > <a href=3D"https://www.freedesktop.org/wiki/Specifications/file-manage= r-interface/" rel=3D"noreferrer noreferrer" target=3D"_blank">https://www.f= reedesktop.org/wiki/Specifications/file-manager-interface/</a><br> <br> </blockquote></div> --000000000000860887064d2cc6bd--