feat: Legal Tools v1 — multilingual landing, dashboard, SSO bridge

- Public landing page at / for unauthenticated users (EN/NO/UK/PL)
- Authenticated / shows Case Workbench dashboard with manifesto strip,
  stats, and launched-tool grid (Transcribe, Timeline, BVJ, Advocate,
  Deep Research, Corpus)
- Added includes/i18n.php with full 4-language translation layer
- Extended layout.php to Case Workbench shell with tool rail, lang switcher
- AI output language normalization extended to en/no/uk/pl in PHP agents
- SSO token validation in bootstrap.php / index.php (dobetternorge.no bridge)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 22:53:27 +02:00
parent ba6c197f1b
commit a3d46f9756
19 changed files with 1149 additions and 238 deletions
+10 -7
View File
@@ -139,9 +139,12 @@ final class DbnLegalToolsService
return [
'tool' => 'ask',
'language' => $language,
'answer' => $language === 'no'
? 'Jeg fant ikke nok kildestøtte i familie-rettskorpuset til å svare sikkert.'
: 'I did not find enough source support in the family-law corpus to answer safely.',
'answer' => match (dbnToolsNormalizeUiLanguage($language)) {
'no' => 'Jeg fant ikke nok kildestøtte i familierettskorpuset til å svare sikkert.',
'uk' => 'Я не знайшов достатньої підтримки в корпусі сімейного права, щоб відповісти безпечно.',
'pl' => 'Nie znalazłem wystarczającego wsparcia źródłowego w korpusie prawa rodzinnego, aby odpowiedzieć bezpiecznie.',
default => 'I did not find enough source support in the family-law corpus to answer safely.',
},
'what_we_found' => $search['what_we_found'],
'evidence_trail' => [],
'what_remains_uncertain' => $search['what_remains_uncertain'],
@@ -160,7 +163,7 @@ final class DbnLegalToolsService
$this->azure->requireChat();
$context = $this->buildEvidenceContext($hits);
$locale = $language === 'no' ? 'Norwegian' : 'English';
$locale = dbnToolsLanguageName($language);
$prompt = <<<PROMPT
Question:
{$question}
@@ -229,7 +232,7 @@ PROMPT;
$text = $this->requirePasteText($text);
$this->azure->requireChat();
$locale = $language === 'no' ? 'Norwegian' : 'English';
$locale = dbnToolsLanguageName($language);
$prompt = <<<PROMPT
Summarize this pasted case-preparation text in {$locale}. Do not invent missing facts.
@@ -296,7 +299,7 @@ PROMPT;
$this->azure->requireChat();
}
$locale = $language === 'no' ? 'Norwegian' : 'English';
$locale = dbnToolsLanguageName($language);
$focusInstruction = match ($focus) {
'deadlines' => "\nFocus specifically on: legal deadlines, filing dates, response windows, appeal periods, and statutory time limits. Deprioritise narrative events with no legal deadline significance.",
@@ -599,7 +602,7 @@ PROMPT;
private function legalJsonSystemPrompt(string $language): string
{
$locale = $language === 'no' ? 'Norwegian' : 'English';
$locale = dbnToolsLanguageName($language);
return <<<PROMPT
You are Do Better Norge Legal Tools in a source-grounded legal preparation workflow.
Use the DBN legal guardrails: