feat: implement multi-tenancy support across knowledge services and normalize TenantId to string type.

This commit is contained in:
2026-05-03 17:52:12 +02:00
parent eac0e9057e
commit e21c24b66d
16 changed files with 334 additions and 94 deletions
@@ -1,7 +1,10 @@
@using MediatR
@using NexusReader.Application.Commands.AI
@using NexusReader.Application.Abstractions.Services
@using NexusReader.UI.Shared.Components.Atoms
@using Microsoft.AspNetCore.Components.Authorization
@inject IMediator Mediator
@inject AuthenticationStateProvider AuthProvider
<div class="groundedness-badge @GetStatusClass()" title="@_result?.Rationale">
@if (_isChecking)
@@ -24,16 +27,29 @@
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.1);
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
transition: all 0.3s ease;
}
.groundedness-badge.status-high { color: var(--nexus-neon); border-color: var(--nexus-neon); }
.groundedness-badge.status-medium { color: #ffaa00; border-color: #ffaa00; }
.groundedness-badge.status-low { color: #ff4444; border-color: #ff4444; }
.groundedness-badge.status-high {
color: var(--nexus-neon);
border-color: var(--nexus-neon);
}
.shimmer { opacity: 0.6; }
.groundedness-badge.status-medium {
color: #ffaa00;
border-color: #ffaa00;
}
.groundedness-badge.status-low {
color: #ff4444;
border-color: #ff4444;
}
.shimmer {
opacity: 0.6;
}
</style>
@code {
@@ -56,7 +72,10 @@
_isChecking = true;
StateHasChanged();
var res = await Mediator.Send(new VerifyGroundednessCommand(Answer, Context));
var authState = await AuthProvider.GetAuthenticationStateAsync();
var tenantId = authState.User.FindFirst("TenantId")?.Value ?? "global";
var res = await Mediator.Send(new VerifyGroundednessCommand(Answer, Context, tenantId));
if (res.IsSuccess)
{
_result = res.Value;
@@ -38,7 +38,7 @@ public sealed class KnowledgeCoordinator : IDisposable
_interactionService.RequestHighlightBlock(nodeId);
}
public async Task ProcessFullPageAsync(string fullContent)
public async Task ProcessFullPageAsync(string fullContent, string tenantId = "global")
{
if (string.IsNullOrWhiteSpace(fullContent)) return;
@@ -49,7 +49,7 @@ public sealed class KnowledgeCoordinator : IDisposable
try
{
var result = await _knowledgeService.GetGraphDataAsync(fullContent);
var result = await _knowledgeService.GetGraphDataAsync(fullContent, tenantId);
if (result.IsSuccess)
{
var packet = result.Value;
@@ -73,12 +73,12 @@ public sealed class KnowledgeCoordinator : IDisposable
_graphService.SetActiveNode(blockId);
}
public async Task<KnowledgePacket?> RequestSummaryAndQuizAsync(string content)
public async Task<KnowledgePacket?> RequestSummaryAndQuizAsync(string content, string tenantId = "global")
{
_quizService.SetHydrating(true);
try
{
var result = await _knowledgeService.GetSummaryAndQuizAsync(content);
var result = await _knowledgeService.GetSummaryAndQuizAsync(content, tenantId);
if (result.IsSuccess)
{
var packet = result.Value;