class NanoRequestContext(object):
    """
    Fields of the context a request may have. This is created by the gateway for the servers.
    """

    # mandatory fields; always present
    PART_SIZE = "part_size"  # int; number of bytes the parts shall be
    PART_APPROX = "part_approx"  # [int, int]; minimum number of of bytes for approximated size, and the step
    S_HMAC_PARTS = "s_hmac_parts"  # [int, int]; range of part numbers the sum-hmac shall be signed on randomly
    OWNER_ACCOUNT_ID = "owner_account_id"  # int; id of the owner of this nano
    ACCOUNT_ID = "account_id"  # int; id of the requesting user
    OWNER_KR = "owner_kr"  # NanoSelfAccountKeyring; keyring of the owner

    # optional fields; their presence depends on the request properties
    PEER_KR = "peer_kr"  # Optional[NanoPeerAccountKeyring]; may be anonymous if that is allowed; None for owner
    REMOTE_IP = "remote_ip"  # Optional[Union[str, bytes]]; remote ip address of the requesting user
    CACHE_KEY = "cache_key"  # Optional[bytes]
    TRANSFER_KEY = "transfer_key"  # Optional[bytes]
    PART = "part"  # Optional[int]
    REQUEST_HEAD = "request_head"  # bytes; the head of the original request as received
    REQUEST_HEAD_LENGTH = 128  # maximum length to be used from the request for fingerprinting and key derivation
    ROOM = "room"  # Optional[dict]; may be None for owner by direct requests

    # fields in the dict of ROOM if not None
    ROOM_ID = "id"  # int; parsed by the gateway from the payload
    ROOM_KR = "kr"  # NanoRoomKeyring
    ROOM_CONFIG_MEMBER = "member"  # int; member permission flags from the config blockchain
    ROOM_CONFIG_GROUP = "group"  # int; group/room permission flags from the config blockchain
    ROOM_APIS = "room_apis"  # Optional[dict]; the locally configured resource-apis for the room if present
    # +type_specific_resource_configs


class NanoBaseRequest(object):
    """
    Nano requests all have a type-key that designates the handler for the operation. They must be prefixed with
    the type of the server that holds the request as f"{prefix}.{type_key}". This request is the payload in the
    requests (NanoServerRequest) that the gateway receives from the server.

    The resource-id field is optional depending on the specific request handler. It is pre-processed by the gateway
    if present, the servers will use the prepared resource-information from the context.
    """

    TYPE_KEY: str = None  # value of the type field for the request

    # mandatory fields
    TYPE = "type"  # str

    # optional fields
    # NOTE: The room id is also received as metadata from the server to facilitate keyring lookup for decrypting the
    # p2p payload. The metadata is only ensured to be authentic when the payload's encryption incorporates a room key.
    # This is not true for the owner's requests. The owner always knows the room-key, so incorporating it in the
    # encryption as authorization proof is useless. Some form of public request serving may also omit the room-secret
    # from the encryption later. Having the server also state the target of the request will disallow malicious users
    # to poll-check other served room ids, because consistency can be checked information provided by two parties. For
    # these reasons we keep the room-id in the payload and enforce consistency with the one from metadata.
    # For simplicity (payload data can be independent of the used encryption) we even require it to be present where
    # the encryption would make sure the id provided from metadata is authentic. This means the owner will not be able
    # to request room-related requests directly. There seems to be no benefit of adding an exemption for the owner's
    # direct requests to this rule.
    ROOM_ID = "room_id"  # str; used for preparing context by the gateway; servers should not need it
    # NOTE: The admin password is protected in transit by the owner's exclusive authenticated encryption. The only
    # Nano that can decrypt the request and see the plain password must be their own. Since they must trust their
    # own Nano, there's no need to pre-hash it on the client side. (would require salt fetching in addition)
    ADMIN_PASSWORD = "admin_password"  # str; used/enforced by specific handlers

    # required fields for mutating requests
    MUTATION_KEY = "mut_key"  # str
    MUTATION_SEQUENCE = "mut_seq"  # int

    # +type_specific_arguments
