# WeKnora Internal Handler Package: Controller Layer Architecture and Implementation

> Explore the WeKnora internal handler package as the controller layer. Learn how it exposes HTTP endpoints, enforces RBAC, and manages task queuing for business logic.

- Repository: [Tencent/WeKnora](https://github.com/tencent/WeKnora)
- Tags: architecture
- Published: 2026-09-13

---

**The `internal/handler` package in Tencent/WeKnora functions as the controller layer that exposes HTTP endpoints, enforces RBAC policies, translates incoming Gin requests into business logic operations, and manages asynchronous task queuing.**

The `internal/handler` package implements the controller pattern in Tencent/WeKnora's Clean Architecture, sitting between the Gin HTTP router and the application service layer. This package handles request validation, permission checks, asynchronous job dispatching, and standardized error responses, ensuring that business logic remains pure and reusable across different transport mechanisms.

## Core Responsibilities of the WeKnora Internal Handler Package

The WeKnora internal handler package manages six critical cross-cutting concerns that bridge the HTTP interface and domain logic.

### HTTP Endpoint Exposure and Routing Integration

Each handler file defines a struct that implements Gin-compatible methods, which the router wires to specific paths. In [`internal/router/routes_knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/router/routes_knowledge.go), the `RegisterKnowledgeRoutes` function connects `KnowledgeHandler` methods to `/knowledge` endpoints:

```go
r := router.Group("/api/v1")
g := router.NewRBACGuards(cfg)
handler.RegisterKnowledgeRoutes(r, knowledgeHandler, g)

```

The registration binds methods like `CreateKnowledgeFromFile` to their respective HTTP routes, keeping routing logic separate from request handling implementation.

### Request Translation and Input Validation

Handlers extract and validate HTTP parameters before delegating to services. The `CreateKnowledgeFromFile` method in [`internal/handler/knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/knowledge.go) demonstrates this flow:

```go
func (h *KnowledgeHandler) CreateKnowledgeFromFile(c *gin.Context) {
    // Verify write permission on the target KB
    kb, kbID, tenantID, _, err := h.validateKnowledgeBaseWriteAccessWithKBID(c, c.Param("id"))
    if err != nil { return }

    // Bind the multipart/form-data payload
    var req types.KnowledgeFileRequest
    if err := c.ShouldBind(&req); err != nil { /* handle error */ }

    // Delegate to the service layer
    knowledge, err := h.kgService.CreateFromFile(c.Request.Context(), kb, req)
    if err != nil { /* handle error */ }

    // Return success JSON
    c.JSON(http.StatusCreated, gin.H{"success": true, "data": knowledge})
}

```

This pattern ensures that transport-layer concerns (JSON binding, context extraction) never leak into the service layer.

### RBAC and Multi-Tenancy Enforcement

Before executing business operations, handlers verify authorization using middleware helpers. The [`internal/handler/knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/knowledge.go) file implements `requireKBOwnershipOrAdmin` and `resolveKnowledgeAndValidateKBAccess` to validate that callers own the target Knowledge Base or possess admin privileges. Similarly, [`internal/handler/auth.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/auth.go) enforces registration-mode restrictions during user signup flows.

These checks occur at the handler boundary, preventing unauthorized requests from reaching core business logic.

### Asynchronous Task Management

For long-running operations, handlers enqueue background jobs using Asynq. The `enqueueKnowledgeListDelete` helper in [`internal/handler/knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/knowledge.go) constructs task payloads and dispatches them to the asynchronous processing queue:

```go
func (h *KnowledgeHandler) enqueueKnowledgeListDelete(kbID uint, knowledgeIDs []uint) error {
    payload := map[string]interface{}{
        "kb_id":         kbID,
        "knowledge_ids": knowledgeIDs,
    }
    data, _ := json.Marshal(payload)
    task := asynq.NewTask("knowledge:batch_delete", data)
    _, err := h.asynqClient.Enqueue(task)
    return err
}

```

This keeps HTTP response times fast while ensuring durable execution of expensive operations.

### Standardized Error Handling and Response Formatting

The package centralizes error translation into the project's `errors.AppError` type. When services return failures, handlers convert them into consistent HTTP responses using constructors like `errors.NewForbiddenError` and `errors.NewNotFoundError`. The `handleDuplicateKnowledgeError` utility in [`internal/handler/knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/knowledge.go) provides reusable patterns for conflict scenarios, ensuring API consumers receive predictable JSON error structures.

## Key Files in the WeKnora Handler Package

The controller layer comprises several specialized handler files and their router counterparts:

| File | Primary Responsibility |
|------|---------------------|
| [`internal/handler/knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/knowledge.go) | Knowledge CRUD operations, permission helpers, and async task enqueueing |
| [`internal/handler/auth.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/auth.go) | Authentication endpoints, registration-mode validation, and user lifecycle |
| [`internal/handler/knowledgebase.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/knowledgebase.go) | Knowledge Base lifecycle management (create, copy, delete, update) |
| [`internal/handler/chunk.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/chunk.go) | Document chunk operations including listing, updating, and deletion |
| [`internal/router/routes_knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/router/routes_knowledge.go) | Route registration that wires handler methods to URL paths |
| [`internal/router/router.go`](https://github.com/Tencent/WeKnora/blob/main/internal/router/router.go) | Gin engine initialization and RBAC guard injection |

## Handler Initialization and Dependency Injection

Handlers receive their dependencies through constructor functions, facilitating testability and inversion of control. The `NewKnowledgeHandler` function accepts configuration, services, and infrastructure clients:

```go
knowledgeHandler := handler.NewKnowledgeHandler(
    cfg,
    kgSvc,          // Knowledge service
    kbSvc,          // Knowledge base service  
    kbShareSvc,     // KB sharing service
    agentShareSvc,  // Agent sharing service
    asynqClient,    // Async task client
    spanRepo,       // Repository for knowledge spans
)

```

This explicit dependency injection pattern ensures handlers remain loosely coupled from their concrete implementations.

## Summary

- The `internal/handler` package implements WeKnora's controller layer, sitting between the Gin router and application services.
- Handlers validate incoming requests, enforce RBAC policies using helpers like `requireKBOwnershipOrAdmin`, and extract validated inputs before calling services.
- Asynchronous operations are dispatched via Asynq through helper methods like `enqueueKnowledgeListDelete`, keeping HTTP responses immediate.
- Consistent API error formatting is achieved through centralized utilities such as `handleDuplicateKnowledgeError` and the `errors.AppError` type system.
- Key files including [`knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/knowledge.go), [`auth.go`](https://github.com/Tencent/WeKnora/blob/main/auth.go), and [`knowledgebase.go`](https://github.com/Tencent/WeKnora/blob/main/knowledgebase.go) encapsulate domain-specific HTTP handling logic while maintaining clean architecture boundaries.

## Frequently Asked Questions

### How does the WeKnora internal handler package enforce security permissions?

The package implements permission checks through dedicated validation helpers defined in handler files. For example, [`internal/handler/knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/knowledge.go) contains `validateKnowledgeBaseWriteAccessWithKBID` and middleware-style functions like `requireKBOwnershipOrAdmin` that verify the caller is either the Knowledge Base creator or holds admin privileges before allowing write operations. These checks execute at the HTTP boundary before any service layer interaction occurs.

### What is the relationship between handlers and the Gin router in WeKnora?

Handlers define methods that conform to Gin's handler signature (`func(*gin.Context)`), but route registration occurs separately in `internal/router/routes_*.go` files. The `RegisterKnowledgeRoutes` function in [`internal/router/routes_knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/router/routes_knowledge.go) explicitly binds `KnowledgeHandler` instances to URL paths and applies RBAC guards. This separation keeps HTTP routing configuration distinct from request processing logic.

### How does WeKnora handle long-running operations in the handler layer?

Handlers offload time-consuming tasks to background workers using Asynq. When processing batch deletions or other expensive operations, methods like `enqueueKnowledgeListDelete` create task payloads and enqueue them via `asynq.NewTask`. The handler returns an immediate HTTP response while the async worker processes the job durably, preventing request timeouts and improving API responsiveness.

### Where is error handling standardized in the WeKnora handler package?

Error standardization occurs through the `errors` package integration and reusable handler utilities. When service calls fail, handlers wrap errors using typed constructors like `errors.NewForbiddenError` or `errors.NewNotFoundError`. The `handleDuplicateKnowledgeError` helper in [`internal/handler/knowledge.go`](https://github.com/Tencent/WeKnora/blob/main/internal/handler/knowledge.go) demonstrates centralized patterns for specific error scenarios, ensuring all API responses follow a consistent JSON structure with appropriate HTTP status codes.