package com.atlassian.bitbucket.mesh.rpc;

/**
 * Constants related to gRPC requests.
 */
public class RpcConstants {

    private RpcConstants() {
        throw new UnsupportedOperationException(getClass().getSimpleName() + " is not intended for instantiation");
    }

    /**
     * Constants related to the {@link MetadataKeys#KEY_TOKEN authentication token}.
     * <p>
     * When authentication is enabled, requests are required to be authenticated with a JWS token set as a gRPC
     * header. Because a Mesh node may receive requests from a large number of clients, the JWS is required to
     * have 2 different headers:
     * <ul>
     *     <li>{@link #HDR_FP "fp"}: The fingerprint of the key the JWS was signed with</li>
     *     <li>{@link #HDR_NID "nid"}: The ID of the node that issued the request
     *     <ul>
     *         <li>{@link #NID_CONTROL_PLANE} indicates the request is from a control plane node</li>
     *         <li>{@link #NID_SIDECAR} indicates the request is from a sidecar node rather than standalone
     *         Mesh node</li>
     *     </ul>
     *     </li>
     * </ul>
     * Those headers are used to allow the node to look up the public key that should be used to verify the JWS's
     * signature.
     * <p>
     * If a JWS is received with a valid signature, its claims are verified further:
     * <ul>
     *     <li>{@code "sub"}: The subject claim is required to be the <i>full method name</i> of the gRPC endpoint
     *     to which the request was sent. For example, {@code "mesh.v1.ManagementService/SetConfiguration"}</li>
     *     <li>For security purposes, clients should always set {@code "iat"} and {@code "exp"} claims on the JWS
     *     to limit its validity, but neither claim is <i>required</i></li>
     * </ul>
     */
    public static class Token {

        public static final String HDR_FP = "fp";
        public static final String HDR_NID = "nid";

        public static final String NID_CONTROL_PLANE = "control-plane";
        public static final String NID_SIDECAR = "sidecar";

        private Token() {
            throw new UnsupportedOperationException(getClass().getSimpleName() + " is not intended for instantiation");
        }
    }
}
