@0xc7941adf5db6bbf0;

using Rust = import "programming_language/rust.capnp";
$Rust.parentModule("schema");

using CSharp = import "programming_language/csharp.capnp";
$CSharp.namespace("FabAccessAPI.Schema");

using UUID = import "utils.capnp".UUID;
using Role = import "role.capnp".Role;

struct User {
    # Intergalactic lifeform that wants to use BFFH

    id @0 :UUID;
    # The UUID of an user is a globally unique, persistent identifier for this user.

    username @1 :Text;
    # username. Locally unique so identifying, but not persistent.

    info @2 :Info;
    interface Info $CSharp.name("InfoInterface") {
        listRoles @0 () -> ( roles :List(Role) );
        # lists explicit roles for this user. A session may have a number of additional, implicit,
        # roles set by their choice of authentication or other context.
    }

    passwd @3 :Passwd;
    interface Passwd {
        changepw @0 ( old :Text, new :Text );
    }

    manage @4 :Manage;
    interface Manage $CSharp.name("ManageInterface") {
        addRole @0 Role;
        removeRole @1 Role;
    }

    admin @5 :Admin;
    interface Admin $CSharp.name("AdminInterface") {
        setpw @0 ( new :Text );
    }

    cardDESFireEV2 @6 :CardDESFireEV2;
    interface CardDESFireEV2 $CSharp.name("CardDESFireInterface") {
        # Card authentication using NXP/MiFare DESFire cards.
        # These cards have the ability to restrict access for data on the cards using symmetric
        # encryption and using a keyed Diffie-Hellman to prevent eavesdropping by any relaying
        # party.
        # A card has several "applications", containing up to 32 files. A file can be read or
        # written. Both kinds of access can be restricted to parties knowing a PSK, on a
        # file-to-file basis.
        # The current system uses File 0001 through File 0004:
        #
        # File 0001 allows public (i.e. unauthenticated) read access and contains the Strings
        # "FABACCESS", "DESFIRE", and "1.0" as packed list of UTF-8 encoded zero-terminated strings:
        # (i.e. "FABACCESS\0DESFIRE\01.0\0")
        # This file serves as sort of magic identifier allowing a server to verify quickly if it is
        # able to use this card at all.
        #
        # File 0002 too allows public read access and contains:
        # - An URL-encoded name of the issuing lab as URN in the format "urn:fabaccess:lab:<labname>"
        #   Examples:
        #     - "urn:fabaccess:lab:innovisionlab"
        #     - "urn:fabaccess:lab:Bibliothek%20Neustadt%20Makerspace"
        #     - "urn:fabaccess:lab:Offene%20Werkstatt%20M%C3%A4rz"
        # - A valid IRI pointing towards the bffd instance running for this lab. This uffd SHOULD be
        #   reachable from the internet. Using private use IP addresses or IRIs that resolve to such
        #   may be necessary for labs behind restrictive firewalls or due to local policy.
        #   The IRI MUST use the "fabaccess" scheme, and SHOULD NOT contain an userinfo, path, query,
        #   or fragment part.
        #   Examples: 
        #     - "fabaccess://innovisionlab.de/"
        #     - "fabaccess://192.168.178.65"
        #     - "fabaccess://fabaccess-server.localnet"
        # - A zero-terminated list of UTF-8 encoded IRIs giving contact options to notify the issuer
        #   or owner in case the card has been lost. Issuers SHOULD set one value on card creation and
        #   MAY allow card owners to change or add values of their choosing.
        #   Examples:
        #     - "mailto:lostcard@innovisionlab.de"
        #     - "https://innovisionlab.de/lostcard"
        #     - "https://werkstatt-märz.de/cardlost.php?action=submitcardlost"
        #
        # File 0003 allows public access or access using a key, at the issuers option.
        # It contains a token that can be used by the home server of the card owner to identify the
        # card owner. The format of the token MUST NOT be relied on by any party except the home
        # server.
        #
        # File 0004 restricts read access to a single key known to the home server of the card
        # owner.
        # It is empty but by being access restricted allows the home server to validate the card as
        # being genuine and thus finalizing the authentication of the user.

        getTokenList @0 () -> ( token_list :List(Data) );
        # Get a list of all user Token currently bound to an user. This will generally be the number
        # of cards they use.

        bind @1 ( token :Data, auth_key :Data ) -> ();
        # Bind a given URL to a given auth key. The server will store both URL and key, so using
        # this frequently will force the server to store large amounts of data. 
        # Trying to bind a new key to an existing URL will fail.

        unbind @2 ( token :Data ) -> ();
        # Unbind the key associated with the given token. This will fail all future attempts to use
        # the card with the associated key.

        genCardToken @3 () -> ( token :Data );
        # Generate a new Token that can be used to access an user in a pseudonymized fashion.
        # This call is extremely cheap to make as the server will not store this Token.

        getMetaInfo @4 () -> ( bytes :Data );
        # Retrieve the blob for File 0001 from the server. The returned bytes are in the correct
        # format to be written to the card as-is.

        getSpaceInfo @5 () -> ( bytes :Data );
        # Retrieve the blob for File 0002 from the server. The returned bytes are in the correct
        # format to be written to the card as-is, but a client MAY add or change some information
        # contained.
    }
}