Documentation
¶
Overview ¶
Package middleware: authentication for browser WebSocket upgrades.
Browsers cannot attach custom headers (Authorization / X-API-Key) to a WebSocket handshake. The sandbox terminal mints a short-lived ticket over a normal authenticated POST and presents it as the ticket query parameter; AttachAuthenticatedUser then installs the same auth session Auth would, given the user the handler already resolved from that ticket.
Index ¶
- Constants
- Variables
- func AllowFileServeAPIKey() gin.HandlerFunc
- func AttachAuthenticatedUser(c *gin.Context, tenantService interfaces.TenantService, ...) bool
- func AuditServiceFromContext(c *gin.Context) interfaces.AuditLogService
- func AuditServiceProvider(svc interfaces.AuditLogService) gin.HandlerFunc
- func Auth(tenantService interfaces.TenantService, userService interfaces.UserService, ...) gin.HandlerFunc
- func DenyAPIKeyPrincipal() gin.HandlerFunc
- func EmbedAuth(svc interfaces.EmbedChannelService, tenantSvc interfaces.TenantService, ...) gin.HandlerFunc
- func EmbedChannelFromContext(ctx context.Context) (*types.EmbedChannel, bool)
- func ErrorHandler() gin.HandlerFunc
- func EvaluateOwnershipOrRole(ctx context.Context, cfg *config.Config, min types.TenantRole, ...) error
- func IsCrossTenantSuperuser(ctx context.Context, cfg *config.Config) bool
- func IsTenantAccessible(ctx context.Context, user *types.User, targetTenantID uint64, ...) bool
- func KBAccessRequest(c *gin.Context) access.KBRequest
- func Language() gin.HandlerFunc
- func Logger() gin.HandlerFunc
- func MCPEndpointAuth(svc interfaces.MCPEndpointService, tenantSvc interfaces.TenantService) gin.HandlerFunc
- func MCPEndpointFromContext(ctx context.Context) (*types.MCPEndpoint, bool)
- func MultipartFormCleanup() gin.HandlerFunc
- func PublicAuthRateLimit() gin.HandlerFunc
- func Recovery() gin.HandlerFunc
- func RequestID() gin.HandlerFunc
- func RequireCrossTenantAccess(cfg *config.Config) gin.HandlerFunc
- func RequireKBAccess(resolveKBID KBIDResolver, requiredPermission types.OrgMemberRole, ...) gin.HandlerFunc
- func RequireOwnershipOrRole(min types.TenantRole, lookup CreatorLookup, cfg *config.Config) gin.HandlerFunc
- func RequirePathTenantMatch(cfg *config.Config) gin.HandlerFunc
- func RequireRole(min types.TenantRole, cfg *config.Config) gin.HandlerFunc
- func RequireRoleOrSystemAdmin(min types.TenantRole, cfg *config.Config) gin.HandlerFunc
- func RequireSystemAdmin(cfg *config.Config) gin.HandlerFunc
- type APIKeyRouteAuthorizer
- func (a *APIKeyRouteAuthorizer) Lookup(method, fullPath string) (APIKeyRoutePolicy, bool)
- func (a *APIKeyRouteAuthorizer) Middleware() gin.HandlerFunc
- func (a *APIKeyRouteAuthorizer) Register(method, fullPath string, policy APIKeyRoutePolicy)
- func (a *APIKeyRouteAuthorizer) RegisteredRoutes() map[string][]string
- type APIKeyRoutePolicy
- type ChunkLookup
- type CreatorLookup
- type KBAccess
- type KBIDResolver
- type KBLookup
- type KnowledgeLookup
Constants ¶
const KBAccessContextKey = "rbac.kb_access"
KBAccessContextKey is the gin.Context key under which a successful KB access resolution is stored.
Variables ¶
var ErrOwnershipForbidden = access.ErrOwnershipForbidden
ErrOwnershipForbidden is returned by EvaluateOwnershipOrRole when the caller is neither the resource creator nor meets the minimum role.
var ErrResourceNotFound = access.ErrResourceNotFound
ErrResourceNotFound is the sentinel a CreatorLookup returns when the :id on the request does not match any row the lookup can see (either the row is genuinely missing or its tenant doesn't match). When a lookup returns this error, RequireOwnershipOrRole intentionally lets the request proceed so the downstream handler can respond with its own 404 — middleware-level 403 would hide real "URL is wrong" failures behind a permissions error, which breaks client diagnostics and operator dashboards.
Functions ¶
func AllowFileServeAPIKey ¶
func AllowFileServeAPIKey() gin.HandlerFunc
AllowFileServeAPIKey guards the tenant-scoped file-proxy routes (/files and the KB-scoped image proxy) for X-API-Key callers. Those routes serve an arbitrary storage path that only carries a tenant segment — there is no KB id in the path a KB-restricted key's allow-list could be checked against — so a KB-restricted key is denied outright (it must download KB content via the KB-scoped routes such as /knowledge/:id/download, which DO enforce the allow-list). A key passes when it is full-access, or when it is NOT KB-restricted and carries the retrieve capability: that is exactly the class of key that can already read any of the tenant's KB content, so exposing the tenant-bounded raw file path (the handler still enforces ValidateStoragePathTenant / the KB owner tenant) grants it nothing new. JWT sessions carry no API-key scope and pass straight through.
func AttachAuthenticatedUser ¶
func AttachAuthenticatedUser( c *gin.Context, tenantService interfaces.TenantService, memberService interfaces.TenantMemberService, cfg *config.Config, user *types.User, jwtTenantID uint64, ) bool
AttachAuthenticatedUser installs the same auth session the Auth middleware would, given an already-resolved user and tenant. On success the request carries the resolved auth session and true is returned; on failure the response has already been written and false is returned.
The tenant is taken from jwtTenantID unless the caller already set X-Tenant-ID, mirroring how Auth honours that header. Membership and role are still resolved from the database by authenticateJWTUser, so passing a user here grants nothing on its own.
func AuditServiceFromContext ¶
func AuditServiceFromContext(c *gin.Context) interfaces.AuditLogService
AuditServiceFromContext fetches the audit service injected by AuditServiceProvider, or returns nil if no provider was wired upstream. Callers MUST nil-check before invoking — audit failure must never break the underlying business operation.
func AuditServiceProvider ¶
func AuditServiceProvider(svc interfaces.AuditLogService) gin.HandlerFunc
AuditServiceProvider returns a gin middleware that injects the audit service into every request's gin.Context. Wiring is centralised in router.NewRouter so each request gets the same instance for the lifetime of the process; the middleware is a no-op when svc is nil (e.g. lite mode where audit isn't configured) so the rbac reject path degrades gracefully.
func Auth ¶
func Auth( tenantService interfaces.TenantService, userService interfaces.UserService, memberService interfaces.TenantMemberService, apiKeyService interfaces.TenantAPIKeyService, cfg *config.Config, ) gin.HandlerFunc
Auth 认证中间件。按顺序尝试三条通道:
- 白名单(isNoAuthAPI)/ OPTIONS 预检 —— 直接放行;
- Bearer JWT —— 成功则走 authenticateJWTUser 完成空间/角色解析; 校验失败不立即拒绝,继续尝试 X-API-Key(保持既有兼容行为: 携带过期 JWT 但同时带有效 API key 的客户端仍可通过);
- X-API-Key —— authenticateAPIKeyRequest。
三条通道都未命中时返回 401;若调用方提交过 Bearer token,错误消息 明确指出 token 无效而不是笼统的 "missing authentication",方便客户端 区分「没登录」和「登录态过期」。
func DenyAPIKeyPrincipal ¶
func DenyAPIKeyPrincipal() gin.HandlerFunc
DenyAPIKeyPrincipal returns a middleware that rejects any X-API-Key principal outright. Use it on routes registered directly on the engine (outside the /api/v1 group) where the APIKeyRouteAuthorizer.Middleware gate does NOT run — the JWT role guards (RequireRole / RequireSystemAdmin / RequireOwnershipOrRole) short-circuit API-key principals on the assumption the gate already authorized them, so an ungated route would otherwise let any valid key through. JWT sessions pass straight through.
func EmbedAuth ¶
func EmbedAuth( svc interfaces.EmbedChannelService, tenantSvc interfaces.TenantService, redisClient *redis.Client, ) gin.HandlerFunc
EmbedAuth validates publish tokens and injects a scoped tenant context for embed routes.
func EmbedChannelFromContext ¶
func EmbedChannelFromContext(ctx context.Context) (*types.EmbedChannel, bool)
EmbedChannelFromContext returns the authenticated embed channel, if any.
func EvaluateOwnershipOrRole ¶
func EvaluateOwnershipOrRole( ctx context.Context, cfg *config.Config, min types.TenantRole, lookup func() (string, error), ) error
EvaluateOwnershipOrRole is the handler adapter for the same lazy decision used by RequireOwnershipOrRole. Body/query-based callers supply a closure so ownership lookup is skipped on exactly the same fast paths as URL routes. Not-found, forbidden and lookup failures remain distinct; each handler maps them to its existing response format and status.
func IsCrossTenantSuperuser ¶
IsCrossTenantSuperuser reports whether ctx carries a user that is authorised for cross-tenant access at this moment. Both the user attribute and the cluster-wide flag must be true; either alone is not enough.
func IsTenantAccessible ¶
func IsTenantAccessible( ctx context.Context, user *types.User, targetTenantID uint64, memberService interfaces.TenantMemberService, cfg *config.Config, ) bool
IsTenantAccessible reports whether `user` is allowed to operate inside `targetTenantID`. The decision order is:
- Home tenant (user.TenantID == targetTenantID): always.
- Cross-tenant superuser: governed by IsCrossTenantSuperuser.
- Multi-tenant member: an active tenant_members row in the target tenant grants access (this is what makes cross-tenant browsing work for non-superusers added via PR 3's member management).
Lookup errors are treated as "not a member" — the safest fallback that doesn't expose other tenants on a transient DB hiccup.
func KBAccessRequest ¶
KBAccessRequest captures caller identity before a guard scopes the request context to a shared resource. The stored grant also supports nested guards.
func Language ¶
func Language() gin.HandlerFunc
Language extracts the user's language preference and injects it into the request context.
Priority (highest to lowest):
- WEKNORA_LANGUAGE environment variable (deployment-level override for document processing language)
- Accept-Language HTTP header (first tag, e.g. "zh-CN,zh;q=0.9" → "zh-CN")
- "zh-CN" hardcoded fallback
WEKNORA_LANGUAGE takes precedence over Accept-Language because the UI locale (menu language) and the document processing language (question/summary generation) are separate concerns. A user may prefer English UI while processing Korean documents.
func Logger ¶
func Logger() gin.HandlerFunc
Logger middleware logs request details with request ID, input and output
func MCPEndpointAuth ¶
func MCPEndpointAuth(svc interfaces.MCPEndpointService, tenantSvc interfaces.TenantService) gin.HandlerFunc
MCPEndpointAuth authenticates calls on the workspace MCP server surface (/mcp/:endpoint_id). The client presents the endpoint's bearer token; on success the request carries the endpoint's workspace, a synthetic machine user, an MCP-endpoint principal and an API-key style scope derived from the endpoint's tool allowlist and knowledge-base scope, so every downstream service applies the same checks it applies to a scoped API key.
func MCPEndpointFromContext ¶
func MCPEndpointFromContext(ctx context.Context) (*types.MCPEndpoint, bool)
MCPEndpointFromContext returns the endpoint authenticated for this request.
func MultipartFormCleanup ¶
func MultipartFormCleanup() gin.HandlerFunc
MultipartFormCleanup 在请求结束后删除 multipart 解析写入系统临时目录的文件。 入参:Gin 请求上下文 c;出参:无。未解析 multipart 表单或仅使用内存的请求不会执行删除。 该中间件应在全部路由之前注册,以覆盖成功、失败和 panic 恢复后的上传请求。
func PublicAuthRateLimit ¶
func PublicAuthRateLimit() gin.HandlerFunc
PublicAuthRateLimit returns a Gin middleware that rate-limits the unauthenticated share-link endpoints by client IP. 429 is mapped through the project's AppError type so it flows through the same error middleware as the rest of the auth surface.
func RequestID ¶
func RequestID() gin.HandlerFunc
RequestID middleware adds a unique request ID to the context
func RequireCrossTenantAccess ¶
func RequireCrossTenantAccess(cfg *config.Config) gin.HandlerFunc
RequireCrossTenantAccess gates a route on the caller being an org-level superuser. Used by /tenants/all, /tenants/search, POST /tenants, GET /tenants — endpoints that operate across tenants rather than inside one.
Unlike RequireRole this is NOT modulated by cfg.Tenant.EnableRBAC: cross-workspace operations are always sensitive regardless of whether per-tenant RBAC is being enforced, so we never log-and-pass.
func RequireKBAccess ¶
func RequireKBAccess( resolveKBID KBIDResolver, requiredPermission types.OrgMemberRole, kbService KBLookup, kbShareService interfaces.KBShareService, agentShareService interfaces.AgentShareService, cfg *config.Config, ) gin.HandlerFunc
RequireKBAccess returns a gin.HandlerFunc that resolves KB access (own / org-shared / via shared agent), enforces the minimum required org-level permission, and on success stores the result under KBAccessContextKey AND rewrites c.Request.Context() to carry the effective tenant ID. Handlers downstream just read tenant from context as before.
On failure the guard aborts with the appropriate HTTP status (400 / 401 / 404 / 403 / 503). Behaviour matches what each handler's effectiveCtxForKB helper used to do; the guard is what consolidates the repetition so a fix in the resolution order propagates to every gated route at once.
Required permission semantics:
- OrgRoleViewer -> read-only routes (the agent-share fallback path activates only at this level)
- OrgRoleEditor -> mutating routes (org-shared editor or own KB)
- OrgRoleAdmin -> share-management routes (only the original sharer / KB owner / Org admin should pass)
The EnableRBAC rollout switch does not apply here. It relaxes the role checks inside a workspace, while ResolveKB always grants a KB's own workspace, so a denial from it means another workspace's KB without a share. Handlers behind this guard load KBs, chunks and wiki pages by ID without a tenant filter, so letting a denial through would lift workspace isolation for the whole rollout window.
func RequireOwnershipOrRole ¶
func RequireOwnershipOrRole(min types.TenantRole, lookup CreatorLookup, cfg *config.Config) gin.HandlerFunc
RequireOwnershipOrRole guards endpoints whose access is allowed for either (a) callers whose role is at least min, or (b) the original creator of the resource being touched.
Use it for KB / agent mutations where Contributors should only manage their own resources but Admins+ have free reign. The lookup closure is responsible for translating the URL into the resource's creator user ID (see CreatorLookup for the return-value contract).
API-key principals skip this human ownership gate; route capabilities and allowed KB scope remain mandatory. For human callers, decision order is:
- role >= min -> allow without running lookup.
- cross-tenant superuser -> allow without running lookup.
- enforcement off -> log, allow without running lookup. This is the critical rollout-safety guarantee: when EnableRBAC is false, the lookup is NEVER invoked, so dormant mode incurs zero extra DB roundtrips on hot per-resource mutation paths.
- lookup returns ErrResourceNotFound -> pass through; let the handler issue the proper 404.
- lookup returns other error -> 503 (transient/unexpected fault). Preserves observability instead of disguising server errors as 403.
- lookup returns the caller's user ID -> allow (ownership match).
- lookup returns "" (tenant-owned, no human creator) -> 403 (we already know role < min from step 1).
- lookup returns a non-empty creator that is not the caller -> 403.
func RequirePathTenantMatch ¶
func RequirePathTenantMatch(cfg *config.Config) gin.HandlerFunc
RequirePathTenantMatch gates a route on the URL :id matching the caller's active tenant context. Cross-tenant superusers bypass the match because their X-Tenant-ID switch was already vetted by the auth middleware.
The router places this on the /tenants/:id group so every per-tenant endpoint (GetTenant / UpdateTenant / DeleteTenant / member management / leave) shares the same check, replacing what was previously a copy-pasted block in each handler.
Reads :id off c.Param. If the param is missing or non-numeric the request is rejected as 400 — the route can't have meaningfully matched without it.
func RequireRole ¶
func RequireRole(min types.TenantRole, cfg *config.Config) gin.HandlerFunc
RequireRole returns a gin middleware that aborts the request with HTTP 403 unless the caller's TenantRole (set by the auth middleware in TenantRoleContextKey) is at least min.
Cross-tenant superusers (User.CanAccessAllTenants) automatically satisfy any role gate. Otherwise rolling out tenant-RBAC would silently break organisation-level operators who own no tenant_members row in the tenant they're administering. The escape hatch is bounded by the existing canAccessTenant gate in auth.go; this middleware does not grant extra reach, only honours what was already approved.
When cfg.Tenant.EnableRBAC is false, the middleware logs the would-be rejection but lets the request through — preserving today's behaviour during the rollout window. Once operators flip the flag to true, the same code paths start rejecting unauthorised callers.
The auth middleware always sets a TenantRole; if for some reason it is missing, TenantRoleFromContext defaults to TenantRoleViewer, which is the safest fail-closed value: anything that requires more than Viewer will reject.
func RequireRoleOrSystemAdmin ¶
func RequireRoleOrSystemAdmin(min types.TenantRole, cfg *config.Config) gin.HandlerFunc
RequireRoleOrSystemAdmin applies the tenant role floor while also allowing platform system administrators. Use it for routes that normally mutate tenant infrastructure but have a narrowly-scoped platform-owned resource (for example built-in models) that system administrators must be able to maintain independently of their role in the active tenant.
API-key behavior remains identical to RequireRole: the APIKeyGate is the source of truth for machine principals, so they short-circuit the role check here as well.
func RequireSystemAdmin ¶
func RequireSystemAdmin(cfg *config.Config) gin.HandlerFunc
RequireSystemAdmin returns a gin middleware that aborts the request with HTTP 403 unless the caller is a system administrator (User.IsSystemAdmin = true).
System administrators operate independently of tenant-scoped roles and are not bound by the per-tenant RBAC matrix. Use this guard for platform-wide administrative endpoints (managing other system admins, editing global settings, cross-workspace operations) where the per-tenant Owner/Admin/Contributor/Viewer ladder does not apply.
Unlike tenant-role guards, this check is always enforced. The tenant RBAC rollout switch only controls per-tenant Owner/Admin/etc. checks; it must not turn platform-wide administration endpoints into "any authenticated user can call this" endpoints.
Types ¶
type APIKeyRouteAuthorizer ¶
type APIKeyRouteAuthorizer struct {
// contains filtered or unexported fields
}
APIKeyRouteAuthorizer is the registry of per-route API-key policies. It is populated at router-construction time (single-threaded) and only read at request time, so it needs no locking.
func NewAPIKeyRouteAuthorizer ¶
func NewAPIKeyRouteAuthorizer() *APIKeyRouteAuthorizer
NewAPIKeyRouteAuthorizer returns an empty authorizer.
func (*APIKeyRouteAuthorizer) Lookup ¶
func (a *APIKeyRouteAuthorizer) Lookup(method, fullPath string) (APIKeyRoutePolicy, bool)
Lookup returns the policy for (method, fullPath) if one was declared.
func (*APIKeyRouteAuthorizer) Middleware ¶
func (a *APIKeyRouteAuthorizer) Middleware() gin.HandlerFunc
Middleware returns the gate middleware. It runs as the first handler on the authenticated API group, after routing (so c.FullPath() is populated). JWT principals pass straight through; API-key principals are authorized purely from the declared policy table.
func (*APIKeyRouteAuthorizer) Register ¶
func (a *APIKeyRouteAuthorizer) Register(method, fullPath string, policy APIKeyRoutePolicy)
Register records the API-key policy for (method, fullPath). fullPath MUST be the same string gin reports via c.FullPath() for the route, otherwise the gate lookup will miss and the route will be denied for API keys. Router-side helpers build fullPath from the group's BasePath so the two stay in sync.
func (*APIKeyRouteAuthorizer) RegisteredRoutes ¶
func (a *APIKeyRouteAuthorizer) RegisteredRoutes() map[string][]string
RegisteredRoutes returns every (method, fullPath) pair the authorizer knows about. Used by the router startup self-check to detect stale path templates.
type APIKeyRoutePolicy ¶
type APIKeyRoutePolicy struct {
// PlatformOnly rejects workspace-bound keys even when they are full-access.
// It is used for control-plane routes under /system/admin and cross-workspace
// tenant lifecycle APIs.
PlatformOnly bool
// RequireFullAccess admits only full-access tenant API keys unless one of
// the listed capabilities also matches. Routes with neither full-access
// requirement nor capabilities are open to any valid API key.
RequireFullAccess bool
// Capabilities is an any-of allow-list for scoped API keys. A capability
// never widens which knowledge bases a key may touch; KB scoping is
// enforced downstream by KBAccess guards and handler scope checks.
Capabilities []types.APIKeyCapability
}
APIKeyRoutePolicy declares how an X-API-Key caller may use a single route.
Design: API-key authorization is a SEPARATE authority from the JWT role/ownership guards. Ownership ("creator OR Admin+") is a human concept and never applies to a machine principal; instead every API-key-accessible route declares one policy here, and the APIKeyGate is the single place that enforces it. Routes that declare no policy are denied for API keys by default (fail-closed), which removes the old "remember to add APIKeyDeny" footgun.
func (APIKeyRoutePolicy) WithCapability ¶
func (p APIKeyRoutePolicy) WithCapability(c types.APIKeyCapability) APIKeyRoutePolicy
WithCapability returns a copy of the policy that additionally admits keys carrying capability c. Multiple calls accumulate (any-of semantics); duplicates are ignored.
type ChunkLookup ¶
type ChunkLookup interface {
GetChunkByIDOnly(ctx context.Context, id string) (*types.Chunk, error)
}
ChunkLookup mirrors KBLookup for resolving a chunk id back to its owning knowledge document, which then resolves to the parent KB. Used by the /chunks/by-id/:id routes that address chunks directly.
type CreatorLookup ¶
CreatorLookup resolves the creator user ID for the resource targeted by the current request, based on whatever is on the gin.Context (URL params, query, body). Implementations live next to the handlers they guard, e.g. handler.kbCreatorLookup(c) reads ":id" and returns KnowledgeBase.CreatorID.
Return value contract:
- (creatorID, nil) where creatorID != "" -> the resource has a recorded owner; ownership match grants access.
- ("", nil) -> "tenant-owned": no human creator was recorded (legacy row or built-in resource); only callers whose role meets the bar may proceed.
- ("", ErrResourceNotFound) -> the :id does not resolve to any row visible to this caller's tenant. Middleware proceeds to the handler so the handler can return 404 instead of masking it as 403.
- ("", other error) -> transient or unexpected failure (DB hiccup, etc.). Middleware returns 503 when enforcement is on so monitoring catches the real fault; when enforcement is off, it logs and lets the request through.
type KBAccess ¶
KBAccess aliases the shared policy result. This adapter resolves route parameters, applies the RBAC rollout switch, and scopes downstream services to the resource tenant. Gin's tenant key retains the authenticated caller.
type KBIDResolver ¶
KBIDResolver tells the guard how to find the kb_id for a given request. Built-in resolvers below cover the param shapes we use: :id, :kb_id, :kbId, :knowledge_id (-> parent KB).
On error, resolvers MUST return either a 4xx apperror (bad request / not found) or a generic Go error for transient/internal failures; the guard maps the latter to 503.
func KBIDFromChunkIDParam ¶
func KBIDFromChunkIDParam(param string, chunkService ChunkLookup) KBIDResolver
KBIDFromChunkIDParam walks chunk_id -> knowledge_id -> kb_id. Used by /chunks/by-id/:id routes that address a chunk directly. The chunk's KnowledgeBaseID is denormalised on the row, so a single lookup is enough — no need to chain through GetKnowledgeByIDOnly.
Not-found / transient split mirrors KBIDFromKnowledgeIDParam.
func KBIDFromKnowledgeIDParam ¶
func KBIDFromKnowledgeIDParam(param string, kgService KnowledgeLookup) KBIDResolver
KBIDFromKnowledgeIDParam reads `:knowledge_id` from the URL, looks up the knowledge document, and returns its KB id. Used by the chunk routes that address a chunk via /chunks/:knowledge_id.
A genuine "not found" maps to 404; transient errors (DB hiccup, service unavailable) are surfaced as a plain Go error so the guard can return 503 instead of pretending the resource doesn't exist (a 404 here would also short-circuit any retry / monitoring).
func KBIDFromParam ¶
func KBIDFromParam(param string) KBIDResolver
KBIDFromParam returns a resolver that reads a fixed gin param.
type KBLookup ¶
type KBLookup interface {
GetKnowledgeBaseByID(ctx context.Context, id string) (*types.KnowledgeBase, error)
}
KBLookup is the minimum surface the guard needs from the knowledge-base service: a single method that turns an ID into a KnowledgeBase pointer (or repo.ErrKnowledgeBaseNotFound). Defining it as a tiny dedicated interface keeps the guard testable without forcing test stubs to satisfy the full KnowledgeBaseService surface.
type KnowledgeLookup ¶
type KnowledgeLookup interface {
GetKnowledgeByIDOnly(ctx context.Context, id string) (*types.Knowledge, error)
}
KnowledgeLookup mirrors KBLookup but for resolving a knowledge id (document id) back to its parent KB. Used by the chunk routes whose URL param is a knowledge_id, not a kb_id.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package asynqdl provides an asynq middleware that records every task whose retry budget is exhausted into the generic task_dead_letters table.
|
Package asynqdl provides an asynq middleware that records every task whose retry budget is exhausted into the generic task_dead_letters table. |