86 lines
2.8 KiB
Go
86 lines
2.8 KiB
Go
// Package session defines the authenticated session-cache contract used by the
|
|
// gateway hot path.
|
|
package session
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
)
|
|
|
|
var (
|
|
// ErrNotFound reports that SessionCache does not currently contain the
|
|
// requested device session identifier.
|
|
ErrNotFound = errors.New("session cache record not found")
|
|
)
|
|
|
|
// Cache resolves authenticated device-session state from the gateway
|
|
// hot path. The canonical implementation is *MemoryCache: a
|
|
// process-local LRU + TTL store that falls back to backend's
|
|
// `/api/v1/internal/sessions/{id}` on miss and listens for
|
|
// `session_invalidation` push events from backend so revoked sessions
|
|
// are reflected immediately without a fresh backend lookup.
|
|
//
|
|
// The Mark* methods are called by the push dispatcher. They flip
|
|
// cached entries to revoked status; subsequent Lookups serve the
|
|
// revoked record directly so authenticated traffic on those sessions
|
|
// is rejected at the edge before reaching backend.
|
|
type Cache interface {
|
|
// Lookup returns the cached record for deviceSessionID. Implementations must
|
|
// wrap ErrNotFound when the cache does not contain the requested record.
|
|
Lookup(ctx context.Context, deviceSessionID string) (Record, error)
|
|
|
|
// MarkRevoked flips the cached record for deviceSessionID to a
|
|
// revoked status. Calling on a missing entry is a no-op.
|
|
MarkRevoked(deviceSessionID string)
|
|
|
|
// MarkAllRevokedForUser flips every cached record belonging to
|
|
// userID to a revoked status. Calling on a user with no cached
|
|
// sessions is a no-op.
|
|
MarkAllRevokedForUser(userID string)
|
|
}
|
|
|
|
// Status identifies the cached lifecycle state of a device session.
|
|
type Status string
|
|
|
|
const (
|
|
// StatusActive reports that the cached device session may continue through
|
|
// later authenticated gateway checks.
|
|
StatusActive Status = "active"
|
|
|
|
// StatusRevoked reports that the cached device session has been revoked and
|
|
// must be rejected before later auth steps run.
|
|
StatusRevoked Status = "revoked"
|
|
)
|
|
|
|
// Record is the minimum authenticated session state required by the gateway
|
|
// before signature verification begins.
|
|
type Record struct {
|
|
// DeviceSessionID is the stable device-session identifier resolved from the
|
|
// hot-path cache.
|
|
DeviceSessionID string
|
|
|
|
// UserID is the authenticated user identity bound to DeviceSessionID.
|
|
UserID string
|
|
|
|
// ClientPublicKey is the standard base64-encoded raw Ed25519 public key
|
|
// material used for request-signature verification.
|
|
ClientPublicKey string
|
|
|
|
// Status reports whether the cached session is active or revoked.
|
|
Status Status
|
|
|
|
// RevokedAtMS optionally records when the device session was revoked.
|
|
RevokedAtMS *int64
|
|
}
|
|
|
|
// IsKnown reports whether s is one of the session states supported by the
|
|
// gateway.
|
|
func (s Status) IsKnown() bool {
|
|
switch s {
|
|
case StatusActive, StatusRevoked:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|