syntax = "proto3"; package svrnty.cqrs.altcha.v1; option go_package = "svrnty.cqrs.altcha.v1;altchapb"; option csharp_namespace = "Svrnty.CQRS.Altcha.Grpc"; // AltchaService is the wire contract between any backend that gates // commands/queries with the [Altcha] attribute and a self-hosted Altcha // implementation. The default .NET client lives in this package; a // reference Go server lives in plan-b's projects/altcha (which vendors // this proto). Keep this file the source of truth for both sides. service AltchaService { // Mint a fresh challenge for the widget to solve. Server-stateless: // the response embeds an HMAC signature that VerifyChallenge re-checks. rpc CreateChallenge(CreateChallengeRequest) returns (Challenge); // Verify a widget-produced solution payload. The server checks // signature + expiry + PoW correctness, then atomically claims the // challenge in a replay-protection cache (e.g. Redis SETNX) so each // solution is single-use across all server replicas. rpc VerifyChallenge(VerifyChallengeRequest) returns (VerifyChallengeResponse); } message CreateChallengeRequest { // Optional per-request complexity override (PoW search-space upper // bound). Higher = slower client solve. Server clamps to its // configured min/max. Omit to use the server default. optional uint32 complexity = 1; } message Challenge { // Hashing algorithm — e.g. "SHA-256" (v2 default). Future versions may // upgrade to PBKDF2 / Argon2; the field lets the widget pick the // right solver. string algorithm = 1; // Hex-encoded hash the client must find a preimage for. Field is // named "challenge_hash" rather than "challenge" to avoid a C# // property/class name collision (the generated message class is // also named Challenge); JSON projection for the widget remaps it. string challenge_hash = 2; // Hex-encoded random salt. Typically embeds the expiry timestamp so // verifiers can re-derive the TTL without server state. string salt = 3; // HMAC-SHA256(secret, algorithm|challenge|salt|maxnumber). Lets // VerifyChallenge confirm the challenge was issued by this server. string signature = 4; // PoW search-space upper bound. Equals the complexity used. uint32 maxnumber = 5; } message VerifyChallengeRequest { // Base64-encoded JSON payload produced by the Altcha widget — the // value carried over the wire on IHasAltchaSolution.AltchaSolution. string payload = 1; } message VerifyChallengeResponse { bool ok = 1; // Diagnostic only; not surfaced to end users. Suggested values: // "signature-invalid", "expired", "pow-incorrect", "replayed", // "redis-unreachable", "malformed". string reason = 2; }