portal

package
v1.41.3 Latest Latest
Warning

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

Go to latest
Published: Mar 14, 2026 License: Apache-2.0 Imports: 28 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

View Source
const MaxContentUploadBytes = 10 << 20

MaxContentUploadBytes is the maximum size for content uploads (10 MB).

View Source
const MaxThumbnailUploadBytes = 512 << 10

MaxThumbnailUploadBytes is the maximum size for thumbnail uploads (512 KB).

Variables

This section is empty.

Functions

func DeriveThumbnailKey added in v1.40.1

func DeriveThumbnailKey(s3Key string) string

DeriveThumbnailKey replaces the filename in an S3 key with "thumbnail.png".

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 ValidateNoticeText added in v1.39.0

func ValidateNoticeText(text string) error

ValidateNoticeText checks that notice text is within length limits.

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"`
	OwnerEmail     string     `json:"owner_email"`
	Name           string     `json:"name"`
	Description    string     `json:"description,omitempty"`
	ContentType    string     `json:"content_type"`
	S3Bucket       string     `json:"s3_bucket"`
	S3Key          string     `json:"s3_key"`
	ThumbnailS3Key string     `json:"thumbnail_s3_key,omitempty"`
	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"`
	Search      string `json:"search,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"`
	ThumbnailS3Key *string  `json:"thumbnail_s3_key,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 AuditMetrics added in v0.36.0

type AuditMetrics interface {
	Timeseries(ctx context.Context, filter audit.TimeseriesFilter) ([]audit.TimeseriesBucket, error)
	Breakdown(ctx context.Context, filter audit.BreakdownFilter) ([]audit.BreakdownEntry, error)
	Overview(ctx context.Context, filter audit.MetricsFilter) (*audit.Overview, error)
}

AuditMetrics provides aggregate audit metrics scoped to individual users.

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
	AuditMetrics    AuditMetrics
	InsightStore    InsightReader
	PersonaResolver PersonaResolver
	// Platform brand (far right of public viewer header)
	BrandName    string // display name (default: "MCP Data Platform")
	BrandLogoSVG string // inline SVG for header logo (empty = default icon)
	BrandURL     string // link URL (e.g., "https://plexara.io"); empty = no link

	// Implementor brand (far left of public viewer header, optional)
	ImplementorName    string // display name (e.g., "ACME Corp"); empty = hidden
	ImplementorLogoSVG string // inline SVG; empty = hidden
	ImplementorURL     string // link URL; empty = no link
}

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 InsightReader added in v0.36.0

type InsightReader interface {
	List(ctx context.Context, filter knowledge.InsightFilter) ([]knowledge.Insight, int, error)
	Stats(ctx context.Context, filter knowledge.InsightFilter) (*knowledge.InsightStats, error)
}

InsightReader provides read-only access to user insights.

type PersonaInfo added in v0.36.0

type PersonaInfo struct {
	Name  string
	Tools []string // resolved tool names from Allow/Deny patterns
}

PersonaInfo holds resolved persona details for the current user.

type PersonaResolver added in v0.36.0

type PersonaResolver func(roles []string) *PersonaInfo

PersonaResolver resolves a user's roles to their persona info.

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"`
	HideExpiration   bool       `json:"hide_expiration"`
	NoticeText       string     `json:"notice_text"`
	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)
	ListActiveShareSummaries(ctx context.Context, assetIDs []string) (map[string]ShareSummary, 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 ShareSummary added in v0.37.0

type ShareSummary struct {
	HasUserShare  bool `json:"has_user_share"`
	HasPublicLink bool `json:"has_public_link"`
}

ShareSummary indicates what kinds of active shares exist for an asset.

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