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
- Variables
- func GenerateIssuerKey() (seedB64 string, publicKeyB64 string, err error)
- func Mint(issuerID string, priv ed25519.PrivateKey, ttl time.Duration) (token string, jti string, err error)
- func ParsePrivateKey(b64key string) (ed25519.PrivateKey, error)
- func PublicKeyB64(priv ed25519.PrivateKey) string
- type Config
- type Payload
Constants ¶
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.
const Prefix = "qci1"
Prefix is segment[0] of every v1 token; verifiers must reject anything else.
Variables ¶
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 ¶
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 ¶
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.