Files
xarmian ba8e20c697 feat: add API token rotation, expiry defaults, and scope enforcement
- New tokens get a default 90-day expiry (configurable via platform
  settings: token_default_expiry_days, token_max_lifetime_days)
- POST /api/v1/auth/tokens/{id}/rotate generates a new secret while
  preserving token metadata; old secret is immediately invalidated
- X-Token-Expires-Soon and X-Token-Expires-At headers warn when a
  token is within 7 days of expiry
- Token scopes are now enforced: "read" restricts to GET/HEAD/OPTIONS,
  "write" and "*" allow all methods
- Existing tokens without expiry continue to work (backward compatible)

Implements TASK-170 under PLAN-15 (Pad Cloud: Hardening).
2026-04-08 18:00:43 +00:00

32 lines
1.1 KiB
Go

package models
import "time"
// APIToken represents a stored API token (without the secret).
type APIToken struct {
ID string `json:"id"`
WorkspaceID string `json:"workspace_id"`
UserID string `json:"user_id,omitempty"`
Name string `json:"name"`
Prefix string `json:"prefix"`
Scopes string `json:"scopes"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
// APITokenCreate is the input for creating a new API token.
type APITokenCreate struct {
Name string `json:"name"`
Scopes string `json:"scopes,omitempty"`
WorkspaceID string `json:"workspace_id,omitempty"` // optional scope
ExpiresIn int `json:"expires_in,omitempty"` // expiry in days (0 = use platform default)
}
// APITokenWithSecret is returned only on creation and includes the
// plaintext token. The token is never stored and cannot be retrieved again.
type APITokenWithSecret struct {
APIToken
Token string `json:"token"` // Only returned once
}