Documentation
¶
Overview ¶
Package feedbackapi holds the portal's feedback surface: threads and their events, the activity feed, the practitioner and SME worklists, asset and collection sign-off, validation responses, and capturing a thread as an insight.
These routes are one family. They share a target model (a thread hangs off an asset, a collection, a prompt, a knowledge page, or nothing), one set of visibility rules over those targets, and one target-gathering policy that the worklist and the activity feed both read. Splitting them apart would fork that policy; leaving them in pkg/portal kept that package at its size ceiling.
The seam owns no policy of its own: every permission decision goes through the shared authorization core in internal/portal/access, which pkg/portal builds once and hands over, so a check cannot mean one thing here and another in the parent.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func KeepAnyShare ¶
func KeepAnyShare(portaldomain.SharePermission) bool
KeepAnyShare keeps shares at any permission.
func KeepEditorShares ¶
func KeepEditorShares(p portaldomain.SharePermission) bool
KeepEditorShares keeps only editor-permission shares.
Types ¶
type ChangesetReader ¶
type ChangesetReader interface {
ListChangesets(ctx context.Context, filter knowledge.ChangesetFilter) ([]knowledge.Changeset, int, error)
}
ChangesetReader provides read access to knowledge changesets, used to surface the thread -> insight -> changeset chain on a feedback thread.
type Config ¶
type Config struct {
Threads threads.ThreadStore
Assets portaldomain.AssetStore
Collections portaldomain.CollectionStore
Prompts prompt.Store
KnowledgePages knowledgepage.Store
Changesets ChangesetReader
MemoryWriter MemoryWriter
Mentions MentionResolver
Notifier ThreadNotifier
// Access is the portal's authorization core, built by the parent so this
// surface and the routes that stayed behind answer permission questions
// the same way.
Access *access.Checker
// PersonaName resolves a caller's roles to their persona name, the value
// stamped on a captured insight. nil yields no persona.
PersonaName func(roles []string) string
}
Config carries everything the feedback routes need. A nil store disables the routes that require it rather than failing them at request time, except where the handler reports the capability as unconfigured (503).
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler serves the portal's feedback routes.
func (*Handler) Register ¶
Register wires the feedback routes onto mux. Threads require a thread store; with none configured the surface registers nothing, which is what a portal running without a database expects.
func (*Handler) RegisterInsightCapture ¶
RegisterInsightCapture wires the "capture feedback as an insight" route. It is separate from Register because it needs a memory writer as well as a thread store, the same pair the route required before the split.
type MemoryWriter ¶
MemoryWriter inserts memory records. It backs the "capture feedback as an insight" path: a reviewer turns a feedback thread into a pending, knowledge-dimension memory record that enters the apply_knowledge review queue.
type MentionResolver ¶
type MentionResolver interface {
ResolveMentions(ctx context.Context, targetType, targetID, body, author string) []string
}
MentionResolver returns the addresses a comment body delivers an @-mention to on a thread target: the names written in the body, minus the author's own address, filtered to the people who can open that target. A nil resolver disables mentions (no database), leaving every token ordinary text.
type ShareKeep ¶
type ShareKeep func(portaldomain.SharePermission) bool
ShareKeep decides whether a share grant counts toward a gathered target set. KeepEditorShares is the "I can act on it" scope (worklist, MCP agent); KeepAnyShare is the "I can view it" scope (activity feed).
type TargetGatherer ¶
type TargetGatherer struct {
Assets portaldomain.AssetStore
Collections portaldomain.CollectionStore
UserID string
Email string
}
TargetGatherer gathers the asset/collection ids a single user can reach, bundling the stores and identity so callers (REST worklist/activity feed, the manage_feedback MCP tool) build it once and ask for asset or collection ids with the desired share scope.
func (TargetGatherer) AssetIDs ¶
AssetIDs returns the ids of assets the user owns plus shared assets whose permission satisfies keep.
func (TargetGatherer) CollectionIDs ¶
CollectionIDs returns the ids of collections the user owns plus shared collections whose permission satisfies keep.
type ThreadNotifier ¶
type ThreadNotifier interface {
// NotifyThreadEvent fires after a successful thread create or event
// append. thread carries the target reference; body is the comment text;
// mentioned carries the @-mentions the body delivers, already filtered to
// people who can open the target.
NotifyThreadEvent(ctx context.Context, thread *threads.Thread, actorEmail, body string, mentioned []string)
}
ThreadNotifier receives the thread half of the portal's notification triggers. It is the narrow view of the platform notifier this surface needs; the share half stays with the routes that create shares. A nil notifier disables thread notifications.