Documentation
¶
Overview ¶
Package accesstoken manages Personal Access Tokens — static bearer credentials a user generates from /profile/tokens and pastes into a remote MCP client (Claude Desktop, Cursor, VSCode plugin, custom CLI). The same token also authenticates any other wick HTTP API a user wires up.
The plaintext token is shown to the user exactly once, at creation time. Wick stores only the SHA-256 hash so the token can be looked up on incoming requests but never reconstructed if the DB leaks.
Token wire format:
wick_pat_<32 hex chars>
The "wick_pat_" prefix is the routing hint auth middleware uses to distinguish static bearers from OAuth JWTs (see internal/docs/ connectors-design.md §8.3).
Index ¶
- Constants
- Variables
- type Handler
- type IssueResult
- type Repo
- func (r *Repo) Create(ctx context.Context, t *entity.PersonalAccessToken) error
- func (r *Repo) FindByHash(ctx context.Context, hash string) (*entity.PersonalAccessToken, error)
- func (r *Repo) GetForUser(ctx context.Context, id, userID string) (*entity.PersonalAccessToken, error)
- func (r *Repo) ListActiveByUser(ctx context.Context, userID string) ([]entity.PersonalAccessToken, error)
- func (r *Repo) ListAllActive(ctx context.Context) ([]entity.PersonalAccessToken, error)
- func (r *Repo) Revoke(ctx context.Context, id, userID string) error
- func (r *Repo) RevokeAny(ctx context.Context, id string) error
- func (r *Repo) TouchLastUsed(ctx context.Context, id string) error
- type Service
- func (s *Service) Authenticate(ctx context.Context, plain string) (userID string, err error)
- func (s *Service) Issue(ctx context.Context, userID, name string) (*IssueResult, error)
- func (s *Service) ListActive(ctx context.Context, userID string) ([]entity.PersonalAccessToken, error)
- func (s *Service) ListAllActive(ctx context.Context) ([]entity.PersonalAccessToken, error)
- func (s *Service) Revoke(ctx context.Context, id, userID string) error
- func (s *Service) RevokeAny(ctx context.Context, id string) error
Constants ¶
const Prefix = "wick_pat_"
Prefix is the leading marker of every wick PAT. MCP auth middleware uses it to route the request into pat.Service.Authenticate before falling back to the OAuth path.
Variables ¶
var ErrInvalid = errors.New("invalid token")
ErrInvalid signals an unparseable or unrecognized token. Returned (rather than wrapped) so middleware can short-circuit cheaply.
var StaticFS embed.FS
Functions ¶
This section is empty.
Types ¶
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler exposes the /profile/tokens and /profile/mcp routes — the user-facing surface for issuing access tokens and reading the MCP install instructions. Tokens are general-purpose bearers (any wick HTTP endpoint accepts them); the MCP page is a thin documentation layer pointing at the same tokens.
func NewHandler ¶
type IssueResult ¶
type IssueResult struct {
Token string // plaintext "wick_pat_..." — never re-derivable
Row *entity.PersonalAccessToken
}
IssueResult bundles the freshly stored row plus the plaintext token. The plaintext is only ever returned by Issue — there is no other API to read it. The handler displays it once and discards it.
type Repo ¶
type Repo struct {
// contains filtered or unexported fields
}
Repo wraps the gorm handle. All queries scope on context so HTTP cancellation propagates into the DB driver.
func (*Repo) FindByHash ¶
FindByHash looks up an active token by its SHA-256 hash. Returns gorm.ErrRecordNotFound when no active row matches.
func (*Repo) GetForUser ¶
func (r *Repo) GetForUser(ctx context.Context, id, userID string) (*entity.PersonalAccessToken, error)
GetForUser loads a token belonging to userID. Used by the revoke handler to enforce ownership before mutating.
func (*Repo) ListActiveByUser ¶
func (r *Repo) ListActiveByUser(ctx context.Context, userID string) ([]entity.PersonalAccessToken, error)
ListActiveByUser returns the user's non-revoked tokens, newest first.
func (*Repo) ListAllActive ¶
ListAllActive returns every non-revoked token across all users, newest first. Drives the admin MCP page; not exposed to non-admin callers.
func (*Repo) Revoke ¶
Revoke stamps RevokedAt on a token belonging to userID. No-op when the row is already revoked.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the runtime façade for token CRUD. The handler at /profile/mcp drives Issue/Revoke; the future MCP middleware drives Authenticate.
func NewService ¶
func NewServiceFromDB ¶
func (*Service) Authenticate ¶
Authenticate validates a plaintext bearer pulled from an incoming request and returns the owning user_id. Returns ErrInvalid for any malformed, unknown, or revoked token so middleware can respond with a uniform 401 — callers MUST NOT distinguish "wrong format" from "wrong token" in the response.
LastUsedAt is stamped best-effort; failure to update does not fail the auth (the DB write is observability, not a gate).
func (*Service) Issue ¶
Issue mints a new token for userID with the given human label. Returns the plaintext token and the persisted row. The plaintext MUST NOT be logged or stored anywhere outside the response back to the user.
func (*Service) ListActive ¶
func (s *Service) ListActive(ctx context.Context, userID string) ([]entity.PersonalAccessToken, error)
ListActive returns the user's non-revoked tokens, newest first. The plaintext is unrecoverable — UI shows the masked form via Row.Masked().
func (*Service) ListAllActive ¶
ListAllActive returns every non-revoked token across all users. Admin-only — exposed via /admin/mcp.