portal

package
v1.83.0 Latest Latest
Warning

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

Go to latest
Published: Jun 10, 2026 License: Apache-2.0 Imports: 35 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 (
	DefaultSearchLimit = 20
)

Search result limits. DefaultSearchLimit is the top-K returned when the caller does not specify one; maxSearchLimit bounds an explicit request so a single ranked query cannot ask for an unbounded result set. They mirror the prompt and memory search limits so every ranked surface clamps the same way.

View Source
const MaxChangeSummaryLength = 500

MaxChangeSummaryLength is the maximum length for a version change summary.

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 AssetIndexText added in v1.81.0

func AssetIndexText(name, description string, tags []string) string

AssetIndexText composes the text an asset is embedded and lexically indexed on for relevance search: its name, description, and tags. The indexjobs asset consumer and the request-path search MUST agree on this composition so a stored embedding lives in the same space as the query; it is defined once here for both. Empty fields are skipped so a sparse asset does not pad the text with blank lines. The lexical arm's portal_asset_fts (migration 000063) composes the same corpus from the same columns.

func CollectionIndexText added in v1.81.0

func CollectionIndexText(name, description, sectionsText string) string

CollectionIndexText composes the text a collection is embedded and lexically indexed on: its name, description, and the denormalized section titles + descriptions (sectionsText). The indexjobs collection consumer and the request-path search MUST agree on this composition; portal_collection_fts (migration 000063) composes the same corpus from the same columns.

func DeriveThumbnailKey added in v1.40.1

func DeriveThumbnailKey(s3Key string) string

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

func ExtensionForContentType added in v1.43.0

func ExtensionForContentType(ct string) string

ExtensionForContentType returns a file extension based on content type.

func RequirePortalAuth

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

RequirePortalAuth creates middleware that enforces portal authentication.

func SectionsText added in v1.81.0

func SectionsText(sections []CollectionSection) string

SectionsText flattens a collection's sections into the denormalized sections_text column: each section's title and description joined in position order, skipping empty fields. The store writes it whenever sections change, and both the lexical FTS index and the embedding read it (transitively, via the column), so the request-path producers cannot drift. Migration 000063 performs a one-time backfill of the same column for pre-existing collections; its SQL is whitespace-equivalent (to_tsvector and the embedder both ignore the extra spaces) rather than byte-identical to this function.

func ValidSharePermission added in v1.42.0

func ValidSharePermission(p string) bool

ValidSharePermission checks whether a permission string is valid.

func ValidateAssetName

func ValidateAssetName(name string) error

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

func ValidateChangeSummary added in v1.43.1

func ValidateChangeSummary(s string) error

ValidateChangeSummary checks that a change summary is within length limits.

func ValidateCollectionDescription added in v1.47.0

func ValidateCollectionDescription(desc string) error

ValidateCollectionDescription checks collection description length.

func ValidateCollectionName added in v1.47.0

func ValidateCollectionName(name string) error

ValidateCollectionName checks that a collection name is valid.

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 ValidateSectionDescription added in v1.47.0

func ValidateSectionDescription(desc string) error

ValidateSectionDescription checks section description length.

func ValidateSectionTitle added in v1.47.0

func ValidateSectionTitle(title string) error

ValidateSectionTitle checks section title length.

func ValidateSections added in v1.47.0

func ValidateSections(sections []CollectionSection) error

ValidateSections checks sections count and content validity.

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" example:"asset_01HK7R8Z8M0Y6A5G1R6FQ2VQNK"`
	OwnerID        string               `json:"owner_id" example:"550e8400-e29b-41d4-a716-446655440000"`
	OwnerEmail     string               `json:"owner_email" example:"alice@example.com"`
	Name           string               `json:"name" example:"Q4 Revenue Dashboard"`
	Description    string               `json:"description,omitempty" example:"Interactive revenue breakdown by region"`
	ContentType    string               `json:"content_type" example:"text/html"`
	S3Bucket       string               `json:"s3_bucket" example:"portal-assets"`
	S3Key          string               `json:"s3_key" example:"assets/01HK7R8Z/content.html"`
	ThumbnailS3Key string               `json:"thumbnail_s3_key,omitempty" example:"assets/01HK7R8Z/thumb.png"`
	SizeBytes      int64                `json:"size_bytes" example:"4200"`
	Tags           []string             `json:"tags"`
	Provenance     Provenance           `json:"provenance"`
	SessionID      string               `json:"session_id,omitempty" example:"sess_abc123"`
	IdempotencyKey string               `json:"idempotency_key,omitempty" example:"export-2026-04-18-abc123"`
	CurrentVersion int                  `json:"current_version" example:"1"`
	Collections    []AssetCollectionRef `json:"collections,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 AssetCollectionRef added in v1.47.0

type AssetCollectionRef struct {
	ID   string `json:"id" example:"col_01HK7R8Z"`
	Name string `json:"name" example:"Q4 Performance Review"`
}

AssetCollectionRef is a lightweight reference to a collection that contains an asset.

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 AssetSearchQuery added in v1.81.0

type AssetSearchQuery struct {
	Embedding []float32 // query vector; nil selects lexical-only ranking
	QueryText string    // raw query text for the lexical arm
	OwnerID   string    // caller identity; mandatory owner scope (owner_id)
	Limit     int       // max results; clamped into [1, maxSearchLimit]
}

AssetSearchQuery describes a relevance ranking request over saved assets. Owner scoping is applied before ranking (you cannot rank an asset you cannot view): OwnerID is mandatory and the search is restricted to the caller's own non-deleted assets. OwnerID (not owner_email) is the scope key because it is the ownership key the rest of the asset subsystem uses — the library list, handleList, and the update/delete ownership checks all key on owner_id, and owner_email is a secondary field that can diverge from it (API-key vs OIDC identity, differing configured email, empty on legacy rows). A nil Embedding selects lexical-only ranking (the graceful-degradation path when no embedding provider is configured); a non-nil Embedding selects hybrid ranking.

func (AssetSearchQuery) EffectiveLimit added in v1.81.0

func (q AssetSearchQuery) EffectiveLimit() int

EffectiveLimit clamps the requested limit into the search bounds.

type AssetSearcher added in v1.81.0

type AssetSearcher interface {
	SearchAssets(ctx context.Context, q AssetSearchQuery) ([]ScoredAsset, error)
}

AssetSearcher ranks the caller's assets by relevance to a query. It is a capability separate from AssetStore: only a backing store that can rank (the PostgreSQL store with pgvector) implements it, so the feature degrades to absent rather than forcing every AssetStore implementation to carry a ranking query.

type AssetStore

type AssetStore interface {
	Insert(ctx context.Context, asset Asset) error
	Get(ctx context.Context, id string) (*Asset, error)
	GetByIDs(ctx context.Context, ids []string) (map[string]*Asset, error)
	GetByIdempotencyKey(ctx context.Context, ownerID, key 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 AssetVersion added in v1.43.0

type AssetVersion struct {
	ID            string    `json:"id" example:"ver_01HK7R9A"`
	AssetID       string    `json:"asset_id" example:"asset_01HK7R8Z8M0Y6A5G1R6FQ2VQNK"`
	Version       int       `json:"version" example:"2"`
	S3Key         string    `json:"s3_key" example:"assets/01HK7R8Z/v2/content.html"`
	S3Bucket      string    `json:"s3_bucket" example:"portal-assets"`
	ContentType   string    `json:"content_type" example:"text/html"`
	SizeBytes     int64     `json:"size_bytes" example:"4500"`
	CreatedBy     string    `json:"created_by" example:"alice@example.com"`
	ChangeSummary string    `json:"change_summary" example:"Updated regional breakdown chart"`
	CreatedAt     time.Time `json:"created_at"`
}

AssetVersion records a single version of an asset's content.

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 Collection added in v1.47.0

type Collection struct {
	ID             string              `json:"id" example:"col_01HK7R8Z"`
	OwnerID        string              `json:"owner_id" example:"550e8400-e29b-41d4-a716-446655440000"`
	OwnerEmail     string              `json:"owner_email" example:"alice@example.com"`
	Name           string              `json:"name" example:"Q4 Performance Review"`
	Description    string              `json:"description" example:"Executive collection with revenue dashboards"`
	ThumbnailS3Key string              `json:"thumbnail_s3_key,omitempty"`
	Config         CollectionConfig    `json:"config"`
	Sections       []CollectionSection `json:"sections"`
	AssetTags      []string            `json:"asset_tags,omitempty"`
	CreatedAt      time.Time           `json:"created_at"`
	UpdatedAt      time.Time           `json:"updated_at"`
	DeletedAt      *time.Time          `json:"deleted_at,omitempty"`
}

Collection represents a curated, ordered group of assets organized into sections.

type CollectionConfig added in v1.47.0

type CollectionConfig struct {
	ThumbnailSize string `json:"thumbnail_size,omitempty" example:"medium"` // "large", "medium", "small", "none"
}

CollectionConfig holds extensible per-collection settings.

type CollectionFilter added in v1.47.0

type CollectionFilter struct {
	OwnerID string `json:"owner_id,omitempty"`
	Search  string `json:"search,omitempty"`
	Limit   int    `json:"limit,omitempty"`
	Offset  int    `json:"offset,omitempty"`
}

CollectionFilter defines filtering criteria for listing collections.

func (*CollectionFilter) EffectiveLimit added in v1.47.0

func (f *CollectionFilter) EffectiveLimit() int

EffectiveLimit returns the limit with defaults applied.

type CollectionItem added in v1.47.0

type CollectionItem struct {
	ID               string    `json:"id" example:"item_01HK7R9D"`
	SectionID        string    `json:"section_id" example:"sec_01HK7R9C"`
	AssetID          string    `json:"asset_id" example:"asset_01HK7R8Z8M0Y6A5G1R6FQ2VQNK"`
	Position         int       `json:"position" example:"0"`
	AssetName        string    `json:"asset_name,omitempty" example:"Q4 Revenue Dashboard"`
	AssetContentType string    `json:"asset_content_type,omitempty" example:"text/html"`
	AssetThumbnail   string    `json:"asset_thumbnail_s3_key,omitempty"`
	AssetDescription string    `json:"asset_description,omitempty" example:"Interactive revenue breakdown"`
	CreatedAt        time.Time `json:"created_at"`
}

CollectionItem is an ordered reference to an asset within a section. Asset* fields are populated by the store on read (JOIN with portal_assets).

type CollectionSearchQuery added in v1.81.0

type CollectionSearchQuery struct {
	Embedding []float32 // query vector; nil selects lexical-only ranking
	QueryText string    // raw query text for the lexical arm
	OwnerID   string    // caller identity; mandatory owner scope (owner_id)
	Limit     int       // max results; clamped into [1, maxSearchLimit]
}

CollectionSearchQuery describes a relevance ranking request over curated collections, scoped to the caller's own non-deleted collections by owner_id (the ownership key, as for assets — see AssetSearchQuery).

func (CollectionSearchQuery) EffectiveLimit added in v1.81.0

func (q CollectionSearchQuery) EffectiveLimit() int

EffectiveLimit clamps the requested limit into the search bounds.

type CollectionSearcher added in v1.81.0

type CollectionSearcher interface {
	SearchCollections(ctx context.Context, q CollectionSearchQuery) ([]ScoredCollection, error)
}

CollectionSearcher ranks the caller's collections by relevance to a query.

type CollectionSection added in v1.47.0

type CollectionSection struct {
	ID           string           `json:"id" example:"sec_01HK7R9C"`
	CollectionID string           `json:"collection_id" example:"col_01HK7R8Z"`
	Title        string           `json:"title" example:"Overview"`
	Description  string           `json:"description" example:"High-level revenue and KPI snapshots"`
	Position     int              `json:"position" example:"0"`
	Items        []CollectionItem `json:"items"`
	CreatedAt    time.Time        `json:"created_at"`
}

CollectionSection is an ordered section within a collection.

type CollectionStore added in v1.47.0

type CollectionStore interface {
	Insert(ctx context.Context, c Collection) error
	Get(ctx context.Context, id string) (*Collection, error)
	List(ctx context.Context, filter CollectionFilter) ([]Collection, int, error)
	Update(ctx context.Context, id, name, description string) error
	UpdateConfig(ctx context.Context, id string, config CollectionConfig) error
	UpdateThumbnail(ctx context.Context, id, thumbnailS3Key string) error
	SoftDelete(ctx context.Context, id string) error
	SetSections(ctx context.Context, collectionID string, sections []CollectionSection) error
}

CollectionStore persists and queries portal collections.

func NewNoopCollectionStore added in v1.47.0

func NewNoopCollectionStore() CollectionStore

NewNoopCollectionStore creates a no-op CollectionStore for use when no database is available.

func NewPostgresCollectionStore added in v1.47.0

func NewPostgresCollectionStore(db *sql.DB) CollectionStore

NewPostgresCollectionStore creates a new PostgreSQL collection store.

type Deps

type Deps struct {
	AssetStore         AssetStore
	ShareStore         ShareStore
	VersionStore       VersionStore
	CollectionStore    CollectionStore
	S3Client           S3Client
	S3Bucket           string
	PublicBaseURL      string
	RateLimit          RateLimitConfig
	OIDCEnabled        bool
	AdminRoles         []string // roles that grant admin access in the portal
	PromptStore        PromptStore
	PromptRegistrar    PromptRegistrar
	PromptInfoProvider PromptInfoProvider
	AuditMetrics       AuditMetrics
	InsightStore       InsightReader
	MemoryStore        MemoryReader
	EmbeddingProvider  embedding.Provider
	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 InsightSearcher added in v1.80.0

type InsightSearcher = knowledge.InsightSearcher

InsightSearcher is the optional relevance-search capability of the insight store, declared canonically in the knowledge package next to its query and result types. The knowledge-search route (and the recall_insight tool) are registered only when the wired InsightStore satisfies it; the memory-backed adapter does, the legacy separate-table store does not.

type MemoryReader added in v1.52.0

type MemoryReader interface {
	List(ctx context.Context, filter memory.Filter) ([]memory.Record, int, error)
	HybridSearch(ctx context.Context, q memory.HybridQuery) ([]memory.ScoredRecord, error)
	LexicalSearch(ctx context.Context, q memory.LexicalQuery) ([]memory.ScoredRecord, error)
}

MemoryReader provides read-only access to user memory records. The search methods back the portal's per-user "my knowledge" search: both queries are scoped to the caller via CreatedBy server-side, so a user can never search another user's records.

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 PromptInfoProvider added in v1.51.0

type PromptInfoProvider interface {
	AllPromptInfos() []registry.PromptInfo
}

PromptInfoProvider returns metadata about system-registered prompts.

type PromptRegistrar added in v1.51.0

type PromptRegistrar interface {
	RegisterRuntimePrompt(p *prompt.Prompt)
	UnregisterRuntimePrompt(name string)
}

PromptRegistrar registers/unregisters prompts with the live MCP server.

type PromptStore added in v1.51.0

type PromptStore interface {
	Create(ctx context.Context, p *prompt.Prompt) error
	Get(ctx context.Context, name string) (*prompt.Prompt, error)
	GetPersonal(ctx context.Context, ownerEmail, name string) (*prompt.Prompt, error)
	GetByID(ctx context.Context, id string) (*prompt.Prompt, error)
	Update(ctx context.Context, p *prompt.Prompt) error
	Delete(ctx context.Context, name string) error
	DeleteByID(ctx context.Context, id string) error
	List(ctx context.Context, filter prompt.ListFilter) ([]prompt.Prompt, error)
	Count(ctx context.Context, filter prompt.ListFilter) (int, error)
}

PromptStore provides prompt persistence for the portal.

type Provenance

type Provenance struct {
	ToolCalls []ProvenanceToolCall `json:"tool_calls,omitempty"`
	SessionID string               `json:"session_id,omitempty" example:"sess_abc123"`
	UserID    string               `json:"user_id,omitempty" example:"550e8400-e29b-41d4-a716-446655440000"`
}

Provenance records the tool call history that produced an artifact.

type ProvenanceToolCall

type ProvenanceToolCall struct {
	ToolName   string         `json:"tool_name" example:"trino_query"`
	Timestamp  string         `json:"timestamp" example:"2026-04-15T14:30:00Z"`
	Parameters map[string]any `json:"parameters,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
	// PutObjectStream uploads body to bucket/key without buffering the
	// whole payload in memory (multipart via the AWS transfer manager),
	// returning the number of bytes written. Callers that need a size
	// limit wrap body in a reader that errors past the limit; the
	// transfer manager aborts the incomplete multipart upload on that
	// read error, so no partial object or orphaned parts remain.
	PutObjectStream(ctx context.Context, bucket, key string, body io.Reader, contentType string) (size int64, err 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 ScoredAsset added in v1.81.0

type ScoredAsset struct {
	Asset Asset   `json:"asset"`
	Score float64 `json:"score"`
}

ScoredAsset pairs an asset with its relevance score in [0,1].

type ScoredCollection added in v1.81.0

type ScoredCollection struct {
	Collection Collection `json:"collection"`
	Score      float64    `json:"score"`
}

ScoredCollection pairs a collection (header + asset tags, no sections) with its relevance score in [0,1].

type Share

type Share struct {
	ID               string          `json:"id" example:"share_01HK7R9B"`
	AssetID          string          `json:"asset_id,omitempty" example:"asset_01HK7R8Z8M0Y6A5G1R6FQ2VQNK"`
	CollectionID     string          `json:"collection_id,omitempty"`
	PromptID         string          `json:"prompt_id,omitempty"`
	Token            string          `json:"token" example:"tk_a1b2c3d4e5f6"`
	CreatedBy        string          `json:"created_by" example:"alice@example.com"`
	SharedWithUserID string          `json:"shared_with_user_id,omitempty"`
	SharedWithEmail  string          `json:"shared_with_email,omitempty" example:"bob@example.com"`
	Permission       SharePermission `json:"permission" example:"viewer"`
	ExpiresAt        *time.Time      `json:"expires_at,omitempty"`
	Revoked          bool            `json:"revoked" example:"false"`
	HideExpiration   bool            `json:"hide_expiration" example:"false"`
	NoticeText       string          `json:"notice_text" example:"Proprietary & Confidential"`
	AccessCount      int             `json:"access_count" example:"3"`
	LastAccessedAt   *time.Time      `json:"last_accessed_at,omitempty"`
	CreatedAt        time.Time       `json:"created_at"`
}

Share represents a share link for an asset, collection, or prompt. Exactly one of AssetID, CollectionID, or PromptID is set.

type SharePermission added in v1.42.0

type SharePermission string

SharePermission defines the access level for a share recipient.

const (
	// PermissionViewer allows read-only access.
	PermissionViewer SharePermission = "viewer"
	// PermissionEditor allows read and write access.
	PermissionEditor SharePermission = "editor"
)

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)
	ListByCollection(ctx context.Context, collectionID string) ([]Share, error)
	ListByPrompt(ctx context.Context, promptID string) ([]Share, error)
	GetUserCollectionPermission(ctx context.Context, collectionID, userID, email string) (SharePermission, error)
	ListSharedWithUser(ctx context.Context, userID, email string, limit, offset int) ([]SharedAsset, int, error)
	ListSharedCollectionsWithUser(ctx context.Context, userID, email string, limit, offset int) ([]SharedCollection, int, error)
	ListSharedPromptsWithUser(ctx context.Context, userID, email string) ([]SharedPromptRef, error)
	ListActiveShareSummaries(ctx context.Context, assetIDs []string) (map[string]ShareSummary, error)
	ListActiveCollectionShareSummaries(ctx context.Context, collectionIDs []string) (map[string]ShareSummary, error)
	GetUserAssetPermissionViaCollection(ctx context.Context, assetID, userID, email string) (SharePermission, error)
	Revoke(ctx context.Context, id string) error
	IncrementAccess(ctx context.Context, id string) error
}

ShareStore persists and queries share links for assets, collections, and prompts.

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" example:"true"`
	HasPublicLink bool `json:"has_public_link" example:"false"`
}

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" example:"share_01HK7R9B"`
	SharedBy   string          `json:"shared_by" example:"alice@example.com"`
	SharedAt   time.Time       `json:"shared_at"`
	Permission SharePermission `json:"permission" example:"viewer"`
}

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

type SharedCollection added in v1.47.0

type SharedCollection struct {
	Collection Collection      `json:"collection"`
	ShareID    string          `json:"share_id" example:"share_01HK7R9E"`
	SharedBy   string          `json:"shared_by" example:"alice@example.com"`
	SharedAt   time.Time       `json:"shared_at"`
	Permission SharePermission `json:"permission" example:"viewer"`
}

SharedCollection combines a Collection with share metadata.

type SharedPrompt added in v1.81.0

type SharedPrompt struct {
	Prompt     prompt.Prompt   `json:"prompt"`
	ShareID    string          `json:"share_id"`
	SharedBy   string          `json:"shared_by"`
	SharedAt   time.Time       `json:"shared_at"`
	Permission SharePermission `json:"permission"`
}

SharedPrompt is a prompt shared with the current user, with share metadata, for the "Shared With Me" listing.

type SharedPromptRef added in v1.81.0

type SharedPromptRef struct {
	PromptID   string
	ShareID    string
	SharedBy   string
	SharedAt   time.Time
	Permission SharePermission
}

SharedPromptRef references a prompt shared with a user along with share metadata. The prompt body is fetched separately from the prompt store so the share store stays decoupled from the prompt domain.

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.

type VersionStore added in v1.43.0

type VersionStore interface {
	// CreateVersion atomically assigns the next version number and records
	// the version. It returns the assigned version number. The Version field
	// in the input is ignored — the actual number is determined by locking
	// the asset row and incrementing current_version.
	CreateVersion(ctx context.Context, version AssetVersion) (int, error)
	ListByAsset(ctx context.Context, assetID string, limit, offset int) ([]AssetVersion, int, error)
	GetByVersion(ctx context.Context, assetID string, version int) (*AssetVersion, error)
	GetLatest(ctx context.Context, assetID string) (*AssetVersion, error)
}

VersionStore persists and queries asset version history.

func NewNoopVersionStore added in v1.43.0

func NewNoopVersionStore() VersionStore

NewNoopVersionStore creates a no-op VersionStore for use when no database is available.

func NewPostgresVersionStore added in v1.43.0

func NewPostgresVersionStore(db *sql.DB) VersionStore

NewPostgresVersionStore creates a new PostgreSQL version store.

Directories

Path Synopsis
Package assetindex is the saved-asset consumer of the shared indexjobs framework (#550).
Package assetindex is the saved-asset consumer of the shared indexjobs framework (#550).
Package collectionindex is the curated-collection consumer of the shared indexjobs framework (#550).
Package collectionindex is the curated-collection consumer of the shared indexjobs framework (#550).

Jump to

Keyboard shortcuts

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