Skip to content

HTTP and identity

Hosting guide covers HTTP limits, authentication, identity, and proxy proofs.

Declarations below are included directly from the public headers.

HTTP server options

vgi_rpc/http.h on GitHub

vgi_rpc/http.h
#ifndef VGI_HTTP_H
#define VGI_HTTP_H
#include "vgi_rpc/identity.h"
#include "vgi_rpc/proof.h"
#include "vgi_rpc/rpc.h"
#ifdef __cplusplus
extern "C" {
#endif
struct VgiHttpIdentity {
    const char *principal;
    const char *domain;
    const char *claims_json;
    const char *failure_reason; /* Closed unauthorized reason code, used on rejection. */
    double auth_time;
    int has_auth_time;
};
struct VgiHttpRequest {
    const char *authorization;
    const char *(*header)(void *, const char *);
    void *state;
};
struct VgiHttpOptions {
    const char *host;
    unsigned port;
    const char *prefix;
    /* Comma-separated token=principal pairs; optional tokens permit anonymous
     * requests without credentials. Supplied invalid credentials are refused. */
    const char *bearer_tokens;
    const char *optional_bearer_tokens;
    const char *signing_key;
    const char *cors_origin;
    const char *access_log; /* JSON lines, no credentials or argument values. */
    const struct VgiIdentityOptions *identity;
    const struct VgiGrantKeys *grant_keys;
    struct VgiProofOptions proof;
    int sticky_enabled;
    unsigned sticky_ttl_seconds;
    size_t max_sessions;
    const char *token_key; /* 64 hexadecimal digits; default is a random process key. */
    const char *const *sticky_echo_names;
    const char *const *sticky_echo_values;
    size_t sticky_echo_count;
    /* Optional authenticated control route. ENOENT delegates to RPC routing;
     * zero handles the request with HTTP 204. path excludes the mount prefix. */
    int (*control)(void *, const char *path, int is_delete, struct VgiRpcCall *);
    void *control_state;
    int compression;
    int64_t max_request_bytes;
    int64_t max_response_bytes;
    int64_t max_externalized_response_bytes;
    size_t max_streams;
    unsigned stream_ttl_seconds;
    /* Reject stream initializers without serialization/resume support. Streams
     * that support it are always stateless: no process-local call cache is used. */
    int require_stateless_streams;
    unsigned max_concurrent_requests;
    /* Zero accepts. EACCES rejects, EAGAIN signals temporary unavailability.
     * Identity strings are copied before the next request. */
    int (*authenticate)(void *, const char *authorization, struct VgiHttpIdentity *,
                        struct ArrowError *);
    int (*authenticate_request)(void *, const struct VgiHttpRequest *, struct VgiHttpIdentity *,
                                struct ArrowError *);
    void *auth_state;
};
void VgiHttpOptionsInit(struct VgiHttpOptions *);
/* Serves until SIGINT/SIGTERM. Prints PORT:<port> after binding (port 0 selects
 * an available port). HTTP bodies, including stream turns, use nanoarrow IPC. */
int VgiRpcServerServeHttp(struct VgiRpcServer *, const struct VgiHttpOptions *,
                          struct ArrowError *);
#ifdef __cplusplus
}
#endif
#endif

Identity and grants

vgi_rpc/identity.h on GitHub

vgi_rpc/identity.h
#ifndef VGI_IDENTITY_H
#define VGI_IDENTITY_H
#include "vgi_rpc/credentials.h"
#include "vgi_rpc/rpc.h"
#ifdef __cplusplus
extern "C" {
#endif
struct VgiTokenIdentity {
    const char *principal, *token_name;
    int64_t ttl_seconds;
};
struct VgiIssuedGrant {
    const char *token, *grant_id;
    double expires_at;
};
/* Hook output strings are borrowed until the hook's release callback runs.
 * Hooks may call VgiRpcFail/SetErrorDetails for structured errors. ENOENT means
 * unresolved/refused; EAGAIN means identity_unavailable with a retry hint. */
struct VgiIdentityOptions {
    int (*resolve_token)(void *, struct VgiRpcCall *, const char *, struct VgiTokenIdentity *);
    int (*mint_grant)(void *, struct VgiRpcCall *, const char *purpose, const char *const *scopes,
                      size_t scope_count, int64_t ttl, struct VgiIssuedGrant *);
    void (*release_result)(void *, void *, int is_grant);
    void *state;
    const char *const *introspect_principals;
    size_t introspect_principal_count;
    double max_auth_age;                   /* Zero uses 900 seconds. */
    const struct VgiGrantKeys *grant_keys; /* Implicit minter if hook absent. */
};
/* Register before serving. Options and everything they reference must outlive
 * the server. Only configured methods appear in reflection and protocol hash. */
int VgiRpcServerSetIdentity(struct VgiRpcServer *, const struct VgiIdentityOptions *,
                            struct ArrowError *);
#ifdef __cplusplus
}
#endif
#endif

Credential helpers

vgi_rpc/credentials.h on GitHub

vgi_rpc/credentials.h
#ifndef VGI_RPC_CREDENTIALS_H
#define VGI_RPC_CREDENTIALS_H
#include "nanoarrow/nanoarrow.h"
#ifdef __cplusplus
extern "C" {
#endif
/* All outputs own their storage. Initialize claims to zero and ArrowBuffers
 * with ArrowBufferInit; reset them after use. Tokens include a terminal NUL
 * outside size_bytes. Open returns EINVAL for invalid credentials, ESTALE for
 * authentic expired/not-yet-valid credentials, or ENOMEM. */
struct VgiGrant {
    int64_t issued_at, expires_at;
    char *grant_id, *principal, *purpose;
    char **scopes;
    size_t scope_count;
};
struct VgiGrantKeys {
    const unsigned char (*keys)[32];
    size_t key_count;
    const char *audience;
    int64_t max_ttl_seconds, clock_skew_seconds;
};
void VgiSigningKey(const void *raw, size_t size, unsigned char key[32]);
void VgiGrantReset(struct VgiGrant *);
int VgiGrantKeysValidate(const struct VgiGrantKeys *);
/* nonce must be NULL in production; a fixed nonce is for test vectors only. */
int VgiGrantMint(const struct VgiGrantKeys *, const struct VgiGrant *,
                 const unsigned char nonce[24], struct ArrowBuffer *token);
int VgiGrantOpen(const struct VgiGrantKeys *, const char *token, double now, struct VgiGrant *);
#ifdef __cplusplus
}
#endif
#endif

Proxy proofs

vgi_rpc/proof.h on GitHub

vgi_rpc/proof.h
#ifndef VGI_RPC_PROOF_H
#define VGI_RPC_PROOF_H
#include "nanoarrow/nanoarrow.h"
#ifdef __cplusplus
extern "C" {
#endif

enum VgiProofMode { VGI_PROOF_OFF, VGI_PROOF_ALLOW, VGI_PROOF_REQUIRE };
struct VgiProofOptions {
    enum VgiProofMode mode;
    const char *origin_id;
    /* Comma-separated kid:hex-secret pairs; each secret is exactly 32 bytes. */
    const char *secrets;
    unsigned skew_seconds;
    /* Zero disables replay detection; otherwise a hard bound on retained nonces. */
    size_t replay_capacity;
};
struct VgiProofResult {
    int verified;
    const char *reason;
    char kid[65];
};
struct VgiProxyProof;
void VgiProofOptionsInit(struct VgiProofOptions *);
/* The configuration is copied. The verifier is safe to share between threads. */
int VgiProxyProofNew(const struct VgiProofOptions *, struct VgiProxyProof **, struct ArrowError *);
void VgiProxyProofFree(struct VgiProxyProof *);
/* Returns EACCES on rejected proofs in REQUIRE mode. Results are diagnostic:
 * never expose their reason or kid in an authentication error response. */
int VgiProxyProofCheck(struct VgiProxyProof *, const char *token, size_t header_count, uint64_t now,
                       struct VgiProofResult *);

#ifdef __cplusplus
}
#endif
#endif