9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
34 lines
1.8 KiB
SQL
34 lines
1.8 KiB
SQL
-- Use-limited invite links: durable invite records for atomic redemption.
|
|
--
|
|
-- Stateless HMAC bearer tokens (v1) cannot enforce use limits: their signed
|
|
-- payload is immutable and no invite row exists to record consumption. This
|
|
-- migration introduces a durable `relay_invites` table that stores only the
|
|
-- SHA-256 hash of an opaque v2 code, never the reusable bearer secret itself.
|
|
--
|
|
-- Every lookup binds both (community_id, token_hash) so a code presented on
|
|
-- the wrong tenant host returns Invalid — there is no cross-tenant lookup by
|
|
-- hash alone. `FOR UPDATE` during claim serializes concurrent claims for one
|
|
-- invite across relay processes; membership insertion, join-policy evidence,
|
|
-- and use_count increment share a single commit so exactly one claimant can
|
|
-- win the final slot.
|
|
--
|
|
-- max_uses is optional: NULL means unlimited (preserving current behavior).
|
|
-- use_count is always incremented for new members, even when unlimited, for
|
|
-- observability. role is pinned to 'member' — invite links never grant admin.
|
|
CREATE TABLE relay_invites (
|
|
community_id UUID NOT NULL REFERENCES communities(id),
|
|
id UUID NOT NULL DEFAULT gen_random_uuid(),
|
|
token_hash BYTEA NOT NULL CHECK (length(token_hash) = 32),
|
|
role TEXT NOT NULL DEFAULT 'member' CHECK (role = 'member'),
|
|
max_uses INTEGER CHECK (max_uses BETWEEN 1 AND 10000),
|
|
use_count INTEGER NOT NULL DEFAULT 0 CHECK (use_count >= 0),
|
|
expires_at TIMESTAMPTZ NOT NULL,
|
|
created_by TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (community_id, id),
|
|
UNIQUE (community_id, token_hash),
|
|
CHECK (max_uses IS NULL OR use_count <= max_uses)
|
|
);
|
|
|
|
CREATE INDEX relay_invites_expires_at_idx ON relay_invites (expires_at);
|