Documentation
¶
Overview ¶
Package subscription manages per-user subscription links: an unguessable capability token that grants read-only access to one user's subscription page (traffic, expiry, devices, per-device QR/config). The token is a 256-bit crypto/rand value, stored AES-GCM encrypted for panel re-display and SHA-256 hashed for lookup — plaintext tokens are never persisted in the clear and never logged (docs/operations/security.md).
Index ¶
- func HashToken(token string) string
- func NewToken() (string, error)
- type Link
- type Service
- func (s *Service) CreateTx(ctx context.Context, tx *sql.Tx, userID string) (*Link, error)
- func (s *Service) Ensure(ctx context.Context, userID string) (*Link, error)
- func (s *Service) ForUser(ctx context.Context, userID string) (*Link, error)
- func (s *Service) ForUsers(ctx context.Context, userIDs []string) (map[string]*Link, error)
- func (s *Service) Regenerate(ctx context.Context, userID string) (*Link, error)
- func (s *Service) RegenerateTx(ctx context.Context, tx *sql.Tx, userID string) (*Link, error)
- func (s *Service) Resolve(ctx context.Context, token string) (string, error)
- func (s *Service) RotateAccess(ctx context.Context, devices *device.Service, userID string) (*Link, int, error)
- func (s *Service) SetRevoked(ctx context.Context, userID string, revoked bool) (*Link, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Link ¶
type Link struct {
UserID string
Token string
CreatedAt time.Time
RotatedAt *time.Time
RevokedAt *time.Time
}
Link is a stored subscription link. Token is the decrypted capability value (empty when decryption fails — the hash lookup path still works).
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service holds the storage rules. All writes serialize on SQLite's write lock; uniqueness of token_hash is enforced by the schema.
func (*Service) CreateTx ¶ added in v0.1.3
CreateTx issues the initial capability inside a caller-owned transaction. Provisioning can therefore commit user, device and recovery link together. The plaintext capability is returned in memory only, never journaled.
func (*Service) Ensure ¶
Ensure returns the user's link, creating one if none exists yet (idempotent — safe to call from the creation flow and the detail page alike).
func (*Service) Regenerate ¶
Regenerate replaces the token (the old one stops working immediately) and clears the revoked flag — a fresh link is a working link.
func (*Service) RegenerateTx ¶
RegenerateTx replaces a link capability inside a caller-owned transaction. Coordinated security workflows use this to rotate the link and every device credential atomically. The returned token exists only in process memory.
func (*Service) Resolve ¶
Resolve maps a presented token onto its user. Any failure — unknown hash, revoked link, malformed input — is the same error (no enumeration oracle). The caller is responsible for loading the user and checking liveness.
func (*Service) RotateAccess ¶ added in v0.1.3
func (s *Service) RotateAccess(ctx context.Context, devices *device.Service, userID string) (*Link, int, error)
RotateAccess replaces the customer link and every existing device key in one transaction. The old capability and configurations are retired even if runtime reconciliation later needs a retry; callers reconcile before reporting an access-rotation success to their client.