portal

package
v0.35.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 8, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Overview

Package portal provides the asset portal data layer for persisting AI-generated artifacts (JSX dashboards, HTML reports, SVG charts).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RequirePortalAuth

func RequirePortalAuth(auth *Authenticator) func(http.Handler) http.Handler

RequirePortalAuth creates middleware that enforces portal authentication.

func ValidateAssetName

func ValidateAssetName(name string) error

ValidateAssetName checks that a name is non-empty and within length limits.

func ValidateContentType

func ValidateContentType(ct string) error

ValidateContentType checks that a content type is non-empty.

func ValidateDescription

func ValidateDescription(desc string) error

ValidateDescription checks that a description is within length limits.

func ValidateEmail added in v0.35.9

func ValidateEmail(email string) error

ValidateEmail checks that an email address has a basic valid format.

func ValidateTags

func ValidateTags(tags []string) error

ValidateTags checks tag count and individual tag length.

Types

type Asset

type Asset struct {
	ID          string     `json:"id"`
	OwnerID     string     `json:"owner_id"`
	Name        string     `json:"name"`
	Description string     `json:"description,omitempty"`
	ContentType string     `json:"content_type"`
	S3Bucket    string     `json:"s3_bucket"`
	S3Key       string     `json:"s3_key"`
	SizeBytes   int64      `json:"size_bytes"`
	Tags        []string   `json:"tags"`
	Provenance  Provenance `json:"provenance"`
	SessionID   string     `json:"session_id,omitempty"`
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at"`
	DeletedAt   *time.Time `json:"deleted_at,omitempty"`
}

Asset represents a persisted AI-generated artifact.

type AssetFilter

type AssetFilter struct {
	OwnerID     string `json:"owner_id,omitempty"`
	ContentType string `json:"content_type,omitempty"`
	Tag         string `json:"tag,omitempty"`
	Limit       int    `json:"limit,omitempty"`
	Offset      int    `json:"offset,omitempty"`
}

AssetFilter defines filtering criteria for listing assets.

func (*AssetFilter) EffectiveLimit

func (f *AssetFilter) EffectiveLimit() int

EffectiveLimit returns the limit with defaults applied.

type AssetStore

type AssetStore interface {
	Insert(ctx context.Context, asset Asset) error
	Get(ctx context.Context, id string) (*Asset, error)
	List(ctx context.Context, filter AssetFilter) ([]Asset, int, error)
	Update(ctx context.Context, id string, updates AssetUpdate) error
	SoftDelete(ctx context.Context, id string) error
}

AssetStore persists and queries portal assets.

func NewNoopAssetStore

func NewNoopAssetStore() AssetStore

NewNoopAssetStore creates a no-op AssetStore for use when no database is available.

func NewPostgresAssetStore

func NewPostgresAssetStore(db *sql.DB) AssetStore

NewPostgresAssetStore creates a new PostgreSQL asset store.

type AssetUpdate

type AssetUpdate struct {
	Name        *string  `json:"name,omitempty"`
	Description *string  `json:"description,omitempty"`
	Tags        []string `json:"tags,omitempty"`
	ContentType string   `json:"content_type,omitempty"`
	S3Key       string   `json:"s3_key,omitempty"`
	SizeBytes   int64    `json:"size_bytes,omitempty"`
	HasContent  bool     `json:"-"` // set when content replacement provides SizeBytes (even if 0)
}

AssetUpdate holds mutable fields for updating an asset. Pointer fields distinguish "no change" (nil) from "clear to empty" (pointer to "").

type Authenticator

type Authenticator struct {
	// contains filtered or unexported fields
}

Authenticator wraps the platform's middleware.Authenticator chain for HTTP portal requests. Unlike the admin authenticator, it does not require a specific persona — any authenticated user can access the portal.

func NewAuthenticator

func NewAuthenticator(auth middleware.Authenticator, opts ...AuthenticatorOption) *Authenticator

NewAuthenticator creates a Authenticator.

func (*Authenticator) Authenticate

func (pa *Authenticator) Authenticate(r *http.Request) (*User, error)

Authenticate extracts credentials from the HTTP request and delegates to the platform authenticator. It checks browser session cookies first, then falls back to token-based authentication.

type AuthenticatorOption

type AuthenticatorOption func(*Authenticator)

AuthenticatorOption configures the portal authenticator.

func WithBrowserAuth

WithBrowserAuth adds cookie-based authentication.

type Deps

type Deps struct {
	AssetStore    AssetStore
	ShareStore    ShareStore
	S3Client      S3Client
	S3Bucket      string
	PublicBaseURL string
	RateLimit     RateLimitConfig
	OIDCEnabled   bool
	AdminRoles    []string // roles that grant admin access in the portal
}

Deps holds dependencies for the portal handler.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler provides portal REST API endpoints.

func NewHandler

func NewHandler(deps Deps, authMiddle func(http.Handler) http.Handler) *Handler

NewHandler creates a new portal API handler.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

type Provenance

type Provenance struct {
	ToolCalls []ProvenanceToolCall `json:"tool_calls,omitempty"`
	SessionID string               `json:"session_id,omitempty"`
	UserID    string               `json:"user_id,omitempty"`
}

Provenance records the tool call history that produced an artifact.

type ProvenanceToolCall

type ProvenanceToolCall struct {
	ToolName  string `json:"tool_name"`
	Timestamp string `json:"timestamp"`
	Summary   string `json:"summary,omitempty"`
}

ProvenanceToolCall records a single tool invocation in the provenance chain.

type RateLimitConfig

type RateLimitConfig struct {
	RequestsPerMinute int `yaml:"requests_per_minute"`
	BurstSize         int `yaml:"burst_size"`
}

RateLimitConfig configures the rate limiter.

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter provides per-IP token bucket rate limiting.

func NewRateLimiter

func NewRateLimiter(cfg RateLimitConfig) *RateLimiter

NewRateLimiter creates a rate limiter from config.

func (*RateLimiter) Allow

func (rl *RateLimiter) Allow(ip string) bool

Allow checks whether a request from the given IP should be allowed.

func (*RateLimiter) Cleanup

func (rl *RateLimiter) Cleanup(maxAge time.Duration)

Cleanup removes stale entries older than the given duration.

func (*RateLimiter) Close

func (rl *RateLimiter) Close()

Close stops the background cleanup goroutine.

func (*RateLimiter) Middleware

func (rl *RateLimiter) Middleware(next http.Handler) http.Handler

Middleware wraps an http.Handler with rate limiting.

type S3Client

type S3Client interface {
	PutObject(ctx context.Context, bucket, key string, data []byte, contentType string) error
	GetObject(ctx context.Context, bucket, key string) ([]byte, string, error)
	DeleteObject(ctx context.Context, bucket, key string) error
	Close() error
}

S3Client abstracts the S3 operations needed by the portal toolkit.

func NewS3ClientAdapter

func NewS3ClientAdapter(client *s3client.Client) S3Client

NewS3ClientAdapter creates an S3Client backed by an mcp-s3 Client.

type Share

type Share struct {
	ID               string     `json:"id"`
	AssetID          string     `json:"asset_id"`
	Token            string     `json:"token"`
	CreatedBy        string     `json:"created_by"`
	SharedWithUserID string     `json:"shared_with_user_id,omitempty"`
	SharedWithEmail  string     `json:"shared_with_email,omitempty"`
	ExpiresAt        *time.Time `json:"expires_at,omitempty"`
	Revoked          bool       `json:"revoked"`
	AccessCount      int        `json:"access_count"`
	LastAccessedAt   *time.Time `json:"last_accessed_at,omitempty"`
	CreatedAt        time.Time  `json:"created_at"`
}

Share represents a share link for an asset.

type ShareStore

type ShareStore interface {
	Insert(ctx context.Context, share Share) error
	GetByID(ctx context.Context, id string) (*Share, error)
	GetByToken(ctx context.Context, token string) (*Share, error)
	ListByAsset(ctx context.Context, assetID string) ([]Share, error)
	ListSharedWithUser(ctx context.Context, userID, email string, limit, offset int) ([]SharedAsset, int, error)
	Revoke(ctx context.Context, id string) error
	IncrementAccess(ctx context.Context, id string) error
}

ShareStore persists and queries share links.

func NewNoopShareStore

func NewNoopShareStore() ShareStore

NewNoopShareStore creates a no-op ShareStore for use when no database is available.

func NewPostgresShareStore

func NewPostgresShareStore(db *sql.DB) ShareStore

NewPostgresShareStore creates a new PostgreSQL share store.

type SharedAsset

type SharedAsset struct {
	Asset    Asset     `json:"asset"`
	ShareID  string    `json:"share_id"`
	SharedBy string    `json:"shared_by"`
	SharedAt time.Time `json:"shared_at"`
}

SharedAsset combines an Asset with share metadata for "shared with me" results.

type User

type User struct {
	UserID string
	Email  string
	Roles  []string
}

User holds information about the authenticated portal user.

func GetUser

func GetUser(ctx context.Context) *User

GetUser returns the User from context, or nil if not set.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL