Add monetization spine + Build Your Own Case (Min Sak)

- Stripe: StripeClient.php, checkout/portal/webhook endpoints, idempotent event handling
- FreeTier: tier-aware credits (free/light/pro/pro_plus), bonus_balance, hourly caps per tier
- pricing.php + billing.php: 4-tier cards, 3 topups, Customer Portal, balance breakdown
- Min Sak: CaseStore.php, AzureDocIntelligence.php, AzureSearchAdmin.php — per-user hybrid RAG
- api/case/: upload, list, delete, ingest-callback (HMAC-auth'd from n8n)
- award-survey-credits: inter-site HMAC endpoint for dobetternorge.no survey bonus
- dashboard.php: tier badge, balance breakdown card, Min Sak CTA, survey CTA
- KorrespondAgent + all 3 other agents: use_my_case toggle wired to dbnToolsCaseContext()
- bootstrap.php: dbnToolsCaseContext(), dbnToolsIntersiteSecret(), dbnToolsCurrentTier()

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 20:52:54 +02:00
parent ed5489d174
commit ba9cddf9a1
30 changed files with 2804 additions and 133 deletions
+11 -42
View File
@@ -9,19 +9,9 @@ if (!dbnToolsIsAuthenticated()) {
}
$uiLang = dbnToolsCurrentLanguage();
$tools = dbnToolsLaunchedTools($uiLang);
$copy = dbnToolsWorkbenchCopy($uiLang);
$langPath = '/workbench.php';
$toolFlow = [
['slug' => 'transcribe', 'step' => '01', 'bring' => $copy['bring_transcribe']],
['slug' => 'timeline', 'step' => '02', 'bring' => $copy['bring_timeline']],
['slug' => 'redact', 'step' => '03', 'bring' => $copy['bring_redact']],
['slug' => 'barnevernet', 'step' => '04', 'bring' => $copy['bring_barnevernet']],
['slug' => 'advocate', 'step' => '05', 'bring' => $copy['bring_advocate']],
['slug' => 'deep-research', 'step' => '06', 'bring' => $copy['bring_research']],
['slug' => 'corpus', 'step' => '07', 'bring' => $copy['bring_corpus']],
];
?>
<!doctype html>
<html lang="<?= htmlspecialchars($uiLang) ?>">
@@ -154,34 +144,9 @@ foreach ($evidenceFields as [$name, $label, $hint]):
</div>
</section>
<section class="workbench-panel workbench-panel--flow" aria-labelledby="workbenchFlowTitle">
<div class="workbench-section-head">
<p class="workbench-kicker">03</p>
<h2 id="workbenchFlowTitle"><?= htmlspecialchars($copy['flow_title']) ?></h2>
</div>
<div class="workbench-flow">
<?php foreach ($toolFlow as $item):
$tool = $tools[$item['slug']] ?? null;
if (!$tool) {
continue;
}
?>
<article class="workbench-step">
<div class="workbench-step__index"><?= htmlspecialchars($item['step']) ?></div>
<div class="workbench-step__body">
<p><?= htmlspecialchars($tool['sub']) ?></p>
<h3><?= htmlspecialchars($tool['label']) ?></h3>
<span><?= htmlspecialchars($item['bring']) ?></span>
</div>
<a class="workbench-tool-link" href="<?= htmlspecialchars($tool['url']) ?>"><?= htmlspecialchars($copy['open_tool']) ?></a>
</article>
<?php endforeach; ?>
</div>
</section>
<section class="workbench-panel workbench-panel--outputs" aria-labelledby="workbenchOutputsTitle">
<div class="workbench-section-head">
<p class="workbench-kicker">04</p>
<p class="workbench-kicker">03</p>
<h2 id="workbenchOutputsTitle"><?= htmlspecialchars($copy['outputs_title']) ?></h2>
</div>
<div class="workbench-checklist">
@@ -199,22 +164,26 @@ foreach ($evidenceFields as [$name, $label, $hint]):
</section>
</form>
<?php if (dbnToolsIsFreeTier()): ?>
<section class="workbench-panel workbench-panel--docs" aria-labelledby="workbenchDocsTitle"
data-my-docs="true">
<div class="workbench-section-head">
<p class="workbench-kicker">05</p>
<p class="workbench-kicker">04</p>
<h2 id="workbenchDocsTitle"><?= htmlspecialchars(dbnToolsT('my_docs_title', $uiLang)) ?></h2>
</div>
<p class="workbench-docs__desc"><?= htmlspecialchars(dbnToolsT('my_docs_desc', $uiLang)) ?></p>
<div class="upload-zone" id="wbUploadZone" role="region" aria-label="Upload documents">
<input type="file" id="wbUploadInput" multiple accept=".pdf,.docx,.txt" aria-label="Choose files">
<div class="upload-prompt">
<span class="upload-icon" aria-hidden="true">&#8679;</span>
<p>Drop files here or <label for="wbUploadInput" class="upload-browse">browse</label></p>
<p class="upload-hint"><strong>PDF</strong>, <strong>DOCX</strong>, <strong>TXT</strong> &mdash; stored for this case.</p>
</div>
</div>
<p id="wbUploadStatus" class="workbench-status" role="status" aria-live="polite" style="margin:8px 0 4px;"></p>
<div id="myDocsList" class="workbench-docs__list" role="list" aria-live="polite">
<p class="workbench-docs__loading"><?= htmlspecialchars(dbnToolsT('loading', $uiLang)) ?></p>
</div>
<a class="secondary-button workbench-docs__cta" href="https://ai.dobetternorge.no/" target="_blank" rel="noopener noreferrer">
<?= htmlspecialchars(dbnToolsT('my_docs_upload_cta', $uiLang)) ?> ↗
</a>
</section>
<?php endif; ?>
</main>
<?php require_once __DIR__ . '/includes/footer.php'; ?>