From 65aa55b211e374e485f9efd162440b900d4dcb21 Mon Sep 17 00:00:00 2001 From: samosvalishe Date: Thu, 21 May 2026 01:24:58 +0300 Subject: [PATCH] =?UTF-8?q?feat(auth):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B7=D0=B0=D0=B3=D0=BE=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D1=83=20Authenticator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Вводит internal/auth с TenantID, sentinel Anonymous, интерфейсом Authenticator и NopAuthenticator (no-op, всегда возвращает Anonymous). doc.go описывает планируемый multi-tenant поток (SQLite/HMAC/deeplink). Реальной реализации пока нет. --- internal/auth/auth.go | 38 ++++++++++++++++++++++++++++++++++++++ internal/auth/doc.go | 23 +++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 internal/auth/auth.go create mode 100644 internal/auth/doc.go diff --git a/internal/auth/auth.go b/internal/auth/auth.go new file mode 100644 index 0000000..f4dcd11 --- /dev/null +++ b/internal/auth/auth.go @@ -0,0 +1,38 @@ +package auth + +import ( + "context" + "net" +) + +// TenantID identifies a tenant in a multi-tenant deployment. +// The zero value ("") is the [Anonymous] sentinel used in single-tenant mode. +type TenantID string + +// Anonymous is the sentinel TenantID used when authentication is disabled +// (single-tenant / no-op mode). All call-sites pass this value until a real +// Authenticator is wired in. +const Anonymous TenantID = "" + +// Authenticator authenticates an incoming connection and returns the +// TenantID it belongs to. Implementations must be safe for concurrent use. +// +// A nil error with [Anonymous] means the connection is accepted in +// non-multi-tenant mode. Any non-nil error must be treated as a rejection +// and the caller must close conn. +type Authenticator interface { + Authenticate(ctx context.Context, conn net.Conn) (TenantID, error) +} + +// NopAuthenticator is a no-op Authenticator that always returns [Anonymous]. +// It is the default when multi-tenant support is not configured. +type NopAuthenticator struct{} + +// compile-time interface check. +var _ Authenticator = NopAuthenticator{} + +// Authenticate implements [Authenticator]. It always succeeds and returns +// [Anonymous] without inspecting conn or ctx. +func (NopAuthenticator) Authenticate(_ context.Context, _ net.Conn) (TenantID, error) { + return Anonymous, nil +} diff --git a/internal/auth/doc.go b/internal/auth/doc.go new file mode 100644 index 0000000..cd9c0e5 --- /dev/null +++ b/internal/auth/doc.go @@ -0,0 +1,23 @@ +// Package auth defines the Authenticator interface and tenant identity types +// for multi-tenant support. +// +// # Current state +// +// Only the scaffold is present. The [NopAuthenticator] is used everywhere and +// returns [Anonymous], preserving existing single-tenant behaviour. +// +// # Planned multi-tenant flow +// +// 1. A real Authenticator (e.g. HMACAuthenticator backed by SQLite) reads a +// short token from the first bytes of conn, validates it against a per-tenant +// shared secret, and returns the matching [TenantID]. +// 2. bondserver.Registry uses the TenantID as part of its de-duplication key so +// ConnIDs from different tenants never collide. +// 3. tcpfwdserver and udpserver resolve connectAddr per-tenant, allowing each +// tenant to target a different backend. +// 4. Deep-link provisioning delivers per-tenant secrets to mobile clients without +// manual configuration. +// +// None of the items above are implemented yet. See notes/AUTH_PLAN.md for the +// detailed design. +package auth