qryptinvite

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package qryptinvite mints single-use, Ed25519-signed invite tokens that the qrypt.chat app accepts to create an ANONYMOUS account. AgentBBS is the trusted issuer: it holds the private key and signs tokens; qrypt.chat verifies them against the issuer's public key registered in its invite_issuers table.

Token format (v1, see the shared qrypt-invite contract):

token        = "qci1." + b64url(payloadJSON) + "." + b64url(sig)
signing input = "qci1." + b64url(payloadJSON)   (the first two segments)
sig          = Ed25519.Sign(issuerPriv, []byte(signing input))
b64url       = base64 URL-encoding, NO padding

There is no alg field and this is not a JWT: Ed25519 is the single fixed algorithm.

Index

Constants

View Source
const (
	DefaultIssuerID  = "agentbbs"
	DefaultRedeemURL = "https://qrypt.chat/anon?invite="
	DefaultTTL       = 168 * time.Hour
	DefaultQuota     = 5
)

DefaultIssuerID, DefaultRedeemURL, DefaultTTL and DefaultQuota are the fallbacks when the corresponding env var is unset.

View Source
const Prefix = "qci1"

Prefix is segment[0] of every v1 token; verifiers must reject anything else.

Variables

View Source
var ErrNoKey = errors.New("qryptinvite: AGENTBBS_QRYPT_ISSUER_KEY is not set (run: agentbbs qrypt-issuer-keygen)")

ErrNoKey means AGENTBBS_QRYPT_ISSUER_KEY is unset, so no tokens can be minted.

Functions

func GenerateIssuerKey

func GenerateIssuerKey() (seedB64 string, publicKeyB64 string, err error)

GenerateIssuerKey creates a fresh Ed25519 issuer keypair for first-time setup. seedB64 is the 32-byte seed (the PRIVATE half — set it as AGENTBBS_QRYPT_ISSUER_KEY); publicKeyB64 is the raw 32-byte public key (register it in qrypt.chat's invite_issuers.ed25519_public_key). Both are standard base64.

func Mint

func Mint(issuerID string, priv ed25519.PrivateKey, ttl time.Duration) (token string, jti string, err error)

Mint produces a signed single-use anonymous invite token for issuerID, valid for ttl. It returns the token string and its jti (the unique id qrypt.chat stores on redeem to prevent double-spend).

func ParsePrivateKey

func ParsePrivateKey(b64key string) (ed25519.PrivateKey, error)

ParsePrivateKey decodes a base64 issuer key into an ed25519.PrivateKey. It accepts either a 32-byte seed (preferred, what GenerateIssuerKey emits) or a full 64-byte private key. Base64 may be standard or URL-encoded, padded or not.

func PublicKeyB64

func PublicKeyB64(priv ed25519.PrivateKey) string

PublicKeyB64 returns the raw 32-byte public key (standard base64) for a private key — the value an operator registers in qrypt.chat.

Types

type Config

type Config struct {
	IssuerID  string        // AGENTBBS_QRYPT_ISSUER_ID (default "agentbbs")
	Key       string        // AGENTBBS_QRYPT_ISSUER_KEY (base64 seed/priv)
	TTL       time.Duration // AGENTBBS_QRYPT_INVITE_TTL (default 168h)
	RedeemURL string        // AGENTBBS_QRYPT_REDEEM_URL (default https://qrypt.chat/anon?invite=)
	Quota     int           // AGENTBBS_QRYPT_INVITE_QUOTA (default 5)
}

Config is the resolved qrypt.chat invite-issuer configuration, read from the environment (see docs/qrypt-invites.md). It is shared by the SSH plugin and the ops CLI so they mint identical tokens.

func ConfigFromEnv

func ConfigFromEnv() Config

ConfigFromEnv reads the AGENTBBS_QRYPT_* environment variables, applying defaults. The key is not validated here; call PrivateKey to parse it.

func (Config) PrivateKey

func (c Config) PrivateKey() (ed25519.PrivateKey, error)

PrivateKey parses the configured issuer key, or returns ErrNoKey if unset.

func (Config) RedeemURLFor

func (c Config) RedeemURLFor(token string) string

RedeemLink returns the full URL a member opens to redeem token.

type Payload

type Payload struct {
	JTI  string `json:"jti"`  // 16 random bytes, hex (32 chars); burns the token
	Iss  string `json:"iss"`  // issuer id, e.g. "agentbbs"
	Tier string `json:"tier"` // always "anonymous" in v1
	Iat  int64  `json:"iat"`  // issued-at (unix seconds)
	Exp  int64  `json:"exp"`  // expiry (unix seconds)
	Uses int    `json:"uses"` // single-use: 1
}

Payload is the JSON body carried in segment[1] of a token. Field tags match the contract exactly; qrypt.chat decodes the same shape.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL