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/