Documentation
¶
Index ¶
- Constants
- func CascadeDeleteUser(ctx context.Context, queries *store.Queries, cfg AccountConfig, uid uuid.UUID, ...) error
- func HashEmail(email string) string
- func ModelsHandler(w http.ResponseWriter, r *http.Request)
- func NewHealthHandler(pool *pgxpool.Pool) http.HandlerFunc
- func OptionalUserUUID(r *http.Request) (uuid.UUID, bool)
- func ParseURLParam(r *http.Request, param string) (uuid.UUID, error)
- func ParseUUIDParamOr400(w http.ResponseWriter, r *http.Request, param string) (uuid.UUID, bool)
- func ProvisionGuestUser(ctx context.Context, queries *store.Queries) (uuid.UUID, string, error)
- func ProvisionUserDefaults(ctx context.Context, queries *store.Queries, userID uuid.UUID)
- func RecordAccessEvent(ctx context.Context, queries *store.Queries, userID uuid.UUID, ...)
- func RequireThreadAccess(r *http.Request, queries *store.Queries, threadID, userID uuid.UUID) error
- func RequireUser(r *http.Request) (uuid.UUID, error)
- func RequireUserOr401(w http.ResponseWriter, r *http.Request) (uuid.UUID, bool)
- func TSPtr(t pgtype.Timestamptz) *string
- func TextPtr(t pgtype.Text) *string
- func UUIDPtr(u pgtype.UUID) *string
- func WelcomeMessages(w http.ResponseWriter, r *http.Request)
- func WriteJSON(w http.ResponseWriter, status int, v any)
- func WriteServerError(w http.ResponseWriter, logMsg string, err error)
- type AccountConfig
- type AccountHandler
- func (h *AccountHandler) DeleteAccount(w http.ResponseWriter, r *http.Request)
- func (h *AccountHandler) GetNodeMenu(w http.ResponseWriter, r *http.Request)
- func (h *AccountHandler) GetPreferredModel(w http.ResponseWriter, r *http.Request)
- func (h *AccountHandler) Logout(w http.ResponseWriter, r *http.Request)
- func (h *AccountHandler) UpdateDisplayName(w http.ResponseWriter, r *http.Request)
- func (h *AccountHandler) UpdateNodeMenu(w http.ResponseWriter, r *http.Request)
- func (h *AccountHandler) UpdatePreferredModel(w http.ResponseWriter, r *http.Request)
- type AuditHook
- type Billing
- type ChatHandler
- func (h *ChatHandler) ClearMessages(w http.ResponseWriter, r *http.Request)
- func (h *ChatHandler) CreateThread(w http.ResponseWriter, r *http.Request)
- func (h *ChatHandler) DeleteThread(w http.ResponseWriter, r *http.Request)
- func (h *ChatHandler) ListThreads(w http.ResponseWriter, r *http.Request)
- func (h *ChatHandler) Messages(w http.ResponseWriter, r *http.Request)
- func (h *ChatHandler) RenameThread(w http.ResponseWriter, r *http.Request)
- func (h *ChatHandler) UpdateScroll(w http.ResponseWriter, r *http.Request)
- type DocumentsHandler
- type Exec
- type FlowsHandler
- func (h *FlowsHandler) Activate(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) Execute(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) Get(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) Publish(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) Reset(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) Unpublish(w http.ResponseWriter, r *http.Request)
- func (h *FlowsHandler) Update(w http.ResponseWriter, r *http.Request)
- type IssuesHandler
- type MarketplaceHandler
- type PricingHook
- type ProviderAdmin
- type ProviderManager
- type UploadHandler
Constants ¶
const TimeFormat = time.RFC3339
TimeFormat is the wire format for all timestamps returned by the API.
Variables ¶
This section is empty.
Functions ¶
func CascadeDeleteUser ¶
func CascadeDeleteUser( ctx context.Context, queries *store.Queries, cfg AccountConfig, uid uuid.UUID, email string, blockRecreate bool, ) error
CascadeDeleteUser permanently (hard) deletes a user. Chats, documents and private flows cascade away; usage/payments are anonymised (ON DELETE SET NULL); published flows are handed to the anonymous sentinel author. cfg. PreDelete settles money first (its failure aborts the delete so no charge is orphaned). When blockRecreate is set the email enters the 30-day cooldown, unless cfg.CooldownExempt clears it.
func HashEmail ¶
HashEmail returns the lowercase-email SHA-256 hex digest used for GDPR-safe access/payment logging.
func ModelsHandler ¶
func ModelsHandler(w http.ResponseWriter, r *http.Request)
func NewHealthHandler ¶
func NewHealthHandler(pool *pgxpool.Pool) http.HandlerFunc
func OptionalUserUUID ¶
OptionalUserUUID returns the authenticated user id if present.
func ParseURLParam ¶
ParseURLParam parses a chi URL parameter as a UUID.
func ParseUUIDParamOr400 ¶
ParseUUIDParamOr400 parses a chi URL parameter as a UUID or writes a 400.
func ProvisionGuestUser ¶
func ProvisionUserDefaults ¶
func RecordAccessEvent ¶
func RecordAccessEvent( ctx context.Context, queries *store.Queries, userID uuid.UUID, email, kind, ip, userAgent string, refID uuid.UUID, )
RecordAccessEvent appends an append-only access-log row tying a user to a real action (login, chat, topup, subscribe) with the caller's IP and user-agent. Best-effort chargeback evidence: failures are logged, never surfaced, and never block the request.
func RequireThreadAccess ¶
RequireThreadAccess returns an error unless the thread belongs to the user.
func RequireUser ¶
RequireUser returns the authenticated user's id, or an error if absent.
func RequireUserOr401 ¶
RequireUserOr401 returns the authenticated user or writes a 401 and false.
func TSPtr ¶
func TSPtr(t pgtype.Timestamptz) *string
TSPtr returns a formatted-string pointer to a valid timestamp, else nil.
func WelcomeMessages ¶
func WelcomeMessages( w http.ResponseWriter, r *http.Request, )
WelcomeMessages serves the seeded welcome conversation as a list of messages so anonymous visitors can preview it before any guest provisioning happens. The shape mirrors /api/threads/{id}/messages so the frontend can render it through the same code path.
func WriteJSON ¶
func WriteJSON(w http.ResponseWriter, status int, v any)
WriteJSON encodes v as a JSON response with the given status.
func WriteServerError ¶
func WriteServerError(w http.ResponseWriter, logMsg string, err error)
WriteServerError logs err with logMsg context and returns a generic 500.
Types ¶
type AccountConfig ¶
type AccountConfig struct {
// PreDelete settles money before a hard delete (hosted: refund refundable
// credit + cancel subscription). A non-nil error aborts the delete.
PreDelete func(ctx context.Context, userID uuid.UUID) error
// CooldownExempt reports whether an email skips the 30-day re-registration
// cooldown (hosted: admins, so they can recreate and re-inherit admin).
CooldownExempt func(ctx context.Context, email string) bool
}
AccountConfig injects the wrapper-specific policy the account endpoints need. Both hooks are nil-safe (the self-host default).
type AccountHandler ¶
type AccountHandler struct {
// contains filtered or unexported fields
}
AccountHandler serves the shared signed-in account endpoints: display name, preferred model, node menu, logout, and account deletion.
func NewAccountHandler ¶
func NewAccountHandler(queries *store.Queries, cfg AccountConfig) *AccountHandler
NewAccountHandler builds the account endpoints.
func (*AccountHandler) DeleteAccount ¶
func (h *AccountHandler) DeleteAccount(w http.ResponseWriter, r *http.Request)
DeleteAccount lets a signed-in user hard-delete their own account after confirming their email.
func (*AccountHandler) GetNodeMenu ¶
func (h *AccountHandler) GetNodeMenu(w http.ResponseWriter, r *http.Request)
GetNodeMenu returns the user's flow-editor node palette.
func (*AccountHandler) GetPreferredModel ¶
func (h *AccountHandler) GetPreferredModel(w http.ResponseWriter, r *http.Request)
GetPreferredModel returns the user's preferred model.
func (*AccountHandler) Logout ¶
func (h *AccountHandler) Logout(w http.ResponseWriter, r *http.Request)
Logout clears the session cookie.
func (*AccountHandler) UpdateDisplayName ¶
func (h *AccountHandler) UpdateDisplayName(w http.ResponseWriter, r *http.Request)
UpdateDisplayName lets a signed-in user rename themselves. The name is trimmed and capped at 40 runes; uniqueness is not required.
func (*AccountHandler) UpdateNodeMenu ¶
func (h *AccountHandler) UpdateNodeMenu(w http.ResponseWriter, r *http.Request)
UpdateNodeMenu replaces the user's flow-editor node palette.
func (*AccountHandler) UpdatePreferredModel ¶
func (h *AccountHandler) UpdatePreferredModel(w http.ResponseWriter, r *http.Request)
UpdatePreferredModel sets the user's preferred model.
type AuditHook ¶
AuditHook records an admin mutation. Wrappers with an audit log (hosted) supply one; self-host passes nil.
type Billing ¶
type Billing interface {
// Preflight runs before any LLM work. On success it returns the per-prompt
// Exec context. On rejection it writes the HTTP response itself and returns
// ok=false, and the caller returns immediately.
Preflight(ctx context.Context, w http.ResponseWriter, userID uuid.UUID) (Exec, bool)
}
Billing authorizes and accounts for a chat prompt. The hosted wrapper injects a real budget/credit implementation; self-host injects a no-op. It is the single seam through which money/abuse policy enters the shared Execute path — core carries no billing schema or policy of its own.
type ChatHandler ¶
type ChatHandler struct {
// contains filtered or unexported fields
}
func NewChatHandler ¶
func NewChatHandler( queries *store.Queries, pool *pgxpool.Pool, cfg coreconfig.HandlerConfig, ) *ChatHandler
func (*ChatHandler) ClearMessages ¶
func (h *ChatHandler) ClearMessages( w http.ResponseWriter, r *http.Request, )
func (*ChatHandler) CreateThread ¶
func (h *ChatHandler) CreateThread( w http.ResponseWriter, r *http.Request, )
func (*ChatHandler) DeleteThread ¶
func (h *ChatHandler) DeleteThread( w http.ResponseWriter, r *http.Request, )
func (*ChatHandler) ListThreads ¶
func (h *ChatHandler) ListThreads( w http.ResponseWriter, r *http.Request, )
func (*ChatHandler) Messages ¶
func (h *ChatHandler) Messages( w http.ResponseWriter, r *http.Request, )
func (*ChatHandler) RenameThread ¶
func (h *ChatHandler) RenameThread( w http.ResponseWriter, r *http.Request, )
func (*ChatHandler) UpdateScroll ¶
func (h *ChatHandler) UpdateScroll( w http.ResponseWriter, r *http.Request, )
type DocumentsHandler ¶
type DocumentsHandler struct {
// contains filtered or unexported fields
}
func NewDocumentsHandler ¶
func NewDocumentsHandler(queries *store.Queries) *DocumentsHandler
func (*DocumentsHandler) Delete ¶
func (h *DocumentsHandler) Delete( w http.ResponseWriter, r *http.Request, )
func (*DocumentsHandler) List ¶
func (h *DocumentsHandler) List( w http.ResponseWriter, r *http.Request, )
type Exec ¶
type Exec interface {
// Begin builds the (billed or unbilled) LLM client that records activity
// against the saved user message; the client is handed to the engine.
Begin(userID, msgID uuid.UUID) flowengine.LLMClient
// SearchCharged returns the web-search charge hook, or nil when unbilled.
SearchCharged() func(ctx context.Context, endpoint string, resultCount int)
// PromptCap is the billed-EUR per-prompt ceiling; 0 means uncapped.
PromptCap() float64
// Guest reports the post-reserve free-prompt count for the guest_llm_calls
// event; ok=false suppresses the event (non-guest / self-host).
Guest() (used, limit int32, ok bool)
// Settle records final cost after execution and returns the total billed
// (0 when unbilled), used for the done event and credit deduction.
Settle(ctx context.Context) float64
}
Exec is the per-prompt billing context returned by a passed Preflight.
type FlowsHandler ¶
type FlowsHandler struct {
// contains filtered or unexported fields
}
func NewFlowsHandler ¶
func NewFlowsHandler( queries *store.Queries, pool *pgxpool.Pool, cfg coreconfig.HandlerConfig, billing Billing, ) *FlowsHandler
func (*FlowsHandler) Activate ¶
func (h *FlowsHandler) Activate( w http.ResponseWriter, r *http.Request, )
func (*FlowsHandler) Create ¶
func (h *FlowsHandler) Create( w http.ResponseWriter, r *http.Request, )
func (*FlowsHandler) Delete ¶
func (h *FlowsHandler) Delete( w http.ResponseWriter, r *http.Request, )
func (*FlowsHandler) Execute ¶
func (h *FlowsHandler) Execute(w http.ResponseWriter, r *http.Request)
Execute runs a chat prompt through the target flow, streaming the result as ndjson. All money/abuse policy is delegated to the injected Billing seam; everything else — flow/thread resolution, message persistence, engine run, auto-title — is shared across every wrapper.
func (*FlowsHandler) Get ¶
func (h *FlowsHandler) Get( w http.ResponseWriter, r *http.Request, )
func (*FlowsHandler) List ¶
func (h *FlowsHandler) List( w http.ResponseWriter, r *http.Request, )
func (*FlowsHandler) Publish ¶
func (h *FlowsHandler) Publish( w http.ResponseWriter, r *http.Request, )
func (*FlowsHandler) Reset ¶
func (h *FlowsHandler) Reset( w http.ResponseWriter, r *http.Request, )
func (*FlowsHandler) Unpublish ¶
func (h *FlowsHandler) Unpublish( w http.ResponseWriter, r *http.Request, )
func (*FlowsHandler) Update ¶
func (h *FlowsHandler) Update( w http.ResponseWriter, r *http.Request, )
type IssuesHandler ¶
type IssuesHandler struct {
// contains filtered or unexported fields
}
func NewIssuesHandler ¶
func NewIssuesHandler(queries *store.Queries) *IssuesHandler
func (*IssuesHandler) Report ¶
func (h *IssuesHandler) Report( w http.ResponseWriter, r *http.Request, )
type MarketplaceHandler ¶
type MarketplaceHandler struct {
// contains filtered or unexported fields
}
func NewMarketplaceHandler ¶
func NewMarketplaceHandler(queries *store.Queries) *MarketplaceHandler
func (*MarketplaceHandler) Get ¶
func (h *MarketplaceHandler) Get( w http.ResponseWriter, r *http.Request, )
func (*MarketplaceHandler) List ¶
func (h *MarketplaceHandler) List( w http.ResponseWriter, r *http.Request, )
func (*MarketplaceHandler) Search ¶
func (h *MarketplaceHandler) Search( w http.ResponseWriter, r *http.Request, )
func (*MarketplaceHandler) Vote ¶
func (h *MarketplaceHandler) Vote( w http.ResponseWriter, r *http.Request, )
type PricingHook ¶
PricingHook fetches per-model pricing overrides for the active providers (e.g. by scraping a provider's pricing page). It is optional and provider-specific, so wrappers inject their own.
type ProviderAdmin ¶
type ProviderAdmin struct {
// contains filtered or unexported fields
}
ProviderAdmin serves the admin provider-CRUD endpoints. It encrypts keys at rest, never returns plaintext, and reloads the live provider set (plus a background model refresh) after every mutation.
func NewProviderAdmin ¶
func NewProviderAdmin( queries *store.Queries, box *crypto.SecretBox, manager *ProviderManager, audit AuditHook, ) *ProviderAdmin
NewProviderAdmin builds the handler. audit may be nil.
func (*ProviderAdmin) Create ¶
func (h *ProviderAdmin) Create(w http.ResponseWriter, r *http.Request)
Create adds a provider, encrypting its key.
func (*ProviderAdmin) Delete ¶
func (h *ProviderAdmin) Delete(w http.ResponseWriter, r *http.Request)
Delete removes a provider.
func (*ProviderAdmin) List ¶
func (h *ProviderAdmin) List(w http.ResponseWriter, r *http.Request)
List returns every provider with key metadata but no plaintext.
func (*ProviderAdmin) Update ¶
func (h *ProviderAdmin) Update(w http.ResponseWriter, r *http.Request)
Update edits a provider. An empty api_key leaves the stored key unchanged; the name is immutable (it keys model routing).
type ProviderManager ¶
type ProviderManager struct {
// contains filtered or unexported fields
}
ProviderManager owns the live LLM-provider set: it rebuilds it from the encrypted DB rows and re-discovers each provider's models. box may be nil when no encryption key is configured, in which case rows carrying a stored key are skipped.
func NewProviderManager ¶
func NewProviderManager( queries *store.Queries, box *crypto.SecretBox, pricingHook PricingHook, ) *ProviderManager
NewProviderManager builds the manager. pricingHook may be nil.
func (*ProviderManager) Refresh ¶
func (m *ProviderManager) Refresh(ctx context.Context)
Refresh re-discovers models from every active provider and rebuilds the catalog. Safe to call on demand after an admin mutates providers. On id collisions the first provider wins.
func (*ProviderManager) Reload ¶
func (m *ProviderManager) Reload(ctx context.Context) error
Reload rebuilds the active provider list purely from the DB. It is the single source of truth: nothing comes from the environment, so an admin fully controls providers at runtime.
func (*ProviderManager) StartModelRefresh ¶
func (m *ProviderManager) StartModelRefresh(ctx context.Context)
StartModelRefresh discovers models once, then re-discovers on a fixed interval until ctx is cancelled.
type UploadHandler ¶
type UploadHandler struct {
// contains filtered or unexported fields
}
func NewUploadHandler ¶
func NewUploadHandler( queries *store.Queries, ) *UploadHandler
func (*UploadHandler) Upload ¶
func (h *UploadHandler) Upload( w http.ResponseWriter, r *http.Request, )