What the internal/application Package Handles in WeKnora: Business Logic and Service Layer
The internal/application package serves as the core business-logic layer of WeKnora, orchestrating wiki page lifecycles, content ingestion, tenant skill execution, and vector search operations while bridging HTTP handlers and data repositories.
The internal/application package sits at the heart of the Tencent/WeKnora architecture, implementing the domain logic that powers the knowledge-base platform. Located between the API handlers in internal/api and the data-access layer in internal/application/repository, this package encapsulates everything from CRUD operations on wiki pages to LLM pipeline orchestration. Understanding its structure is essential for developers extending WeKnora’s capabilities or debugging service-level issues.
Core Responsibilities of the internal/application Package
The package organizes its functionality into cohesive service modules that handle distinct domain concerns. Each service operates as a facade over lower-level repositories, enforcing business rules and transaction boundaries.
Wiki Page Orchestration and Lifecycle Management
At the center of the package, internal/application/service/wiki_page.go defines the wikiPageService struct, which implements the full CRUD lifecycle for wiki content. This service handles versioning, bidirectional link maintenance, and graph generation for knowledge bases.
Key capabilities include:
- CreatePage and UpdatePage: Persist wiki content while parsing internal links and maintaining slug integrity.
- GetGraph: Generate subgraph views of the knowledge base with BFS ego-mode traversal (implemented via
bfsEgoSlugs). - RebuildLinks: Repair and synchronize bidirectional wiki links after content changes.
- Content normalization: Utilities like
normalizeSlugandrewriteDeadWikiLinksensure consistent URL slugs and repair broken references.
Content Ingest Pipeline
The ingest subsystem processes bulk wiki imports through a coordinated pipeline spread across wiki_ingest.go, wiki_ingest_dedup.go, and wiki_ingest_cite.go. This pipeline handles taxonomy extraction, deduplication, citation processing, and dead-link repair when migrating existing content into WeKnora.
Tenant Skill Execution Engine
WeKnora supports per-tenant plugins called "skills" that augment the knowledge base or run custom LLM pipelines. The internal/application/service/tenant_skill_service.go file implements the skill lifecycle management, including:
- Verification and installation of skill packages.
- Runtime execution control via
RunSkill. - Cleanup and resource isolation between tenants.
This allows individual knowledge bases to load custom logic without affecting the core system stability.
Vector Store Abstraction for Semantic Search
The vectorstore.go file provides a unified interface for semantic retrieval via the VectorStoreService. It abstracts multiple backends—such as OpenSearch and SSRF-safe SQLite—behind methods like AddEmbedding and Search. This abstraction lets the rest of the application perform vector operations without coupling to specific storage engines.
Web Search Integration
To augment LLM prompts with real-time data, web_search_provider.go encapsulates remote web-search providers. It handles provider authentication, result fetching, and content filtering before injecting search context into chat pipelines.
Access Control and Knowledge Base Sharing
Security logic resides in internal/application/access/ownership.go and related kb_* files. These modules enforce ownership verification, write-permission checks, and sharing mechanics before any service modifies knowledge base data. This ensures that multi-tenant isolation and collaboration rules are applied consistently across all operations.
User and Tenant Utilities
Supporting infrastructure for authentication and configuration lives in files like user_env.go, user_oidc_security.go, and user_admin_create.go. These handle JWT validation, OIDC verification, environment-variable resolution, and tenant-scoped context propagation throughout the service layer.
Chat Pipeline Helpers
The chat_pipeline/ subdirectory contains specialized utilities for LLM workflows, including rerank.go for result reordering and memory_recall.go for conversational context retrieval. These helpers implement query expansion, semantic reranking, and session memory management to improve response quality.
Key Source Files and Their Roles
Understanding the file layout helps navigate the codebase effectively:
service/wiki_page.go: Central service for wiki CRUD, graph computation, and link management.service/wiki_ingest.go: Entry point for batch content ingestion and taxonomy processing.service/tenant_skill_service.go: Coordination of plugin installation and execution.service/vectorstore.go: Abstraction over vector databases for embedding storage and similarity search.service/web_search_provider.go: Integration layer for external search APIs.access/ownership.go: Domain-level permission checks and KB ownership logic.service/user_env.go: Configuration and context resolution for user sessions.service/chat_pipeline/rerank.go: Algorithms for reordering search results based on relevance.
Practical Code Examples
The following snippets demonstrate typical interactions with the internal/application services.
Creating a Wiki Page
svc := NewWikiPageService(repo, chunkRepo, kbService, taskPendingRepo, redisClient)
ctx := types.WithWikiEditSource(context.Background(), types.WikiEditSourceUser)
page := &types.WikiPage{
KnowledgeBaseID: "kb-123",
Slug: "example-page",
Title: "Example Page",
Content: "This is a [[linked-page]] in markdown.",
PageType: types.WikiPageTypeSummary,
}
created, err := svc.CreatePage(ctx, page)
if err != nil {
// handle error
}
fmt.Println("Created page ID:", created.ID)
Generating a Knowledge Graph
graphReq := &types.WikiGraphRequest{
KnowledgeBaseID: "kb-123",
Mode: types.WikiGraphModeOverview,
Limit: 200,
}
graph, err := svc.GetGraph(context.Background(), graphReq)
if err != nil {
// handle error
}
fmt.Printf("Graph contains %d nodes, %d edges\n", len(graph.Nodes), len(graph.Edges))
Executing a Tenant Skill
skillSvc := NewTenantSkillService(repo, taskPendingRepo, redisClient)
err := skillSvc.RunSkill(context.Background(), "kb-123", "my-skill-id")
if err != nil {
// handle error
}
Summary
- The
internal/applicationpackage implements WeKnora’s business-logic layer, isolating domain rules from HTTP transport and data persistence. - Core services manage wiki page lifecycles, batch ingestion, tenant skill execution, and vector search operations.
- Access control is enforced centrally through the
access/subdirectory, ensuring secure multi-tenant operations. - The package provides abstractions for web search and vector stores, allowing backend implementations to change without affecting API consumers.
- All service implementations reside in
internal/application/service/, with clear separation between orchestration logic and repository concerns.
Frequently Asked Questions
What is the difference between internal/application and internal/api in WeKnora?
The internal/api package handles HTTP routing, request validation, and JSON serialization, while internal/application contains the domain logic that processes those requests. The API layer translates HTTP calls into service method invocations, and the application layer enforces business rules, coordinates transactions, and interacts with repositories. This separation ensures that core logic remains transport-agnostic and testable without HTTP dependencies.
How does the internal/application package handle vector search?
The package exposes semantic search through service/vectorstore.go, which defines the VectorStoreService interface with methods like AddEmbedding and Search. This service abstracts underlying storage engines—such as OpenSearch or SQLite—providing a unified API for the rest of the system. Callers simply invoke Search with a query embedding, and the service handles backend-specific query construction and result retrieval.
Where are tenant skills defined and executed within the application layer?
Tenant skills are managed by service/tenant_skill_service.go. This service handles the installation, validation, and runtime execution of per-tenant plugins. The RunSkill method accepts a knowledge base ID and skill identifier, loads the appropriate plugin code in an isolated context, and executes it against the tenant’s data. This architecture allows custom extensions without modifying core WeKnora binaries.
How is access control enforced in the internal/application package?
Access control logic resides in access/ownership.go and associated knowledge base permission files. Before executing destructive operations, services invoke ownership checks to verify that the requesting user has write permissions or ownership rights for the target knowledge base. These checks run after authentication (handled upstream) but before any repository modifications, ensuring consistent enforcement of multi-tenant security policies.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →