From ec58fc30f840ce85ea06eb3d07457640a84f941c Mon Sep 17 00:00:00 2001 From: groot Date: Thu, 23 Jul 2026 08:49:28 +0200 Subject: [PATCH] 1.8.2 - Anpassungen am Bulk-System --- CHANGELOG.md | 6 ++++++ Makefile | 2 +- README.md | 2 +- bulkweb/static/bulk.css | 4 +++- bulkweb/static/bulk.js | 30 ++++++++++++++++++++++++++++-- bulkweb/templates/index.html | 4 ++-- deploy/kubernetes.yaml | 2 +- deploy/swarm-stack.yaml | 2 +- docs/BACKGROUND-PAGE.md | 2 +- docs/LICENSE-CLIENT.md | 2 +- docs/LICENSE-INTEGRATION.md | 2 +- internal/app/licensing.go | 2 +- internal/bulk/server.go | 2 +- internal/bulk/server_test.go | 34 ++++++++++++++++++++++++++++++++++ internal/marketing/content.go | 4 ++-- openapi.yaml | 2 +- web/templates/background.html | 2 +- web/templates/index.html | 2 +- web/templates/marketing.html | 2 +- 19 files changed, 88 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b50c2a5..90a3fed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 1.8.2 - 2026-07-23 + +- Fixed the Bulk results view so it previews the same accessible badge-plus-visible-text disclosure used by the recommended `embedHtml` export. +- Renamed the raw badge link to `SVG (nur Grafik)` to make clear that the standalone SVG is only the visual asset and not the recommended first-exposure integration. +- Kept Bulk HTML exports unchanged on `embedHtml`; this release fixes the misleading preview/link presentation rather than introducing a second rendering path. + ## 1.8.1 - 2026-07-23 - Added an accessible first-exposure embed with visible link text next to the SVG badge instead of relying on SVG/`alt` information alone. diff --git a/Makefile b/Makefile index 1433d99..545ed75 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ build-bulk: CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o bin/ai-disclosure-bulk ./cmd/bulk docker-build: - docker build -t ai-disclosure-standard:1.8.1-local . + docker build -t ai-disclosure-standard:1.8.2-local . docker-build-bulk: docker build -f Dockerfile.bulk -t ai-disclosure-bulk:1.0.0-local . diff --git a/README.md b/README.md index 8727fa0..f80048b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# AI Disclosure Standard 1.8.1 +# AI Disclosure Standard 1.8.2 Ein zustandsloser Go-Dienst für sichtbare und maschinenlesbare Erklärungen zur KI-Nutzung in Artikeln, Webseiten und einzelnen Inhaltsbestandteilen. diff --git a/bulkweb/static/bulk.css b/bulkweb/static/bulk.css index 7b29211..3661913 100644 --- a/bulkweb/static/bulk.css +++ b/bulkweb/static/bulk.css @@ -1,5 +1,7 @@ :root{--bg:#f4f2ed;--surface:#fff;--ink:#171717;--muted:#646464;--line:#d7d3ca;--accent:#262626;--danger:#8f2d1f;--good:#276749;--warn:#8a5a11;--radius:18px;--shadow:0 16px 40px rgba(0,0,0,.07)} -*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--bg);color:var(--ink);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;line-height:1.55}a{color:inherit}.site-header,footer{width:min(1180px,calc(100% - 40px));margin:auto;padding:24px 0;display:flex;align-items:center;justify-content:space-between;gap:24px}.site-header nav,footer nav{display:flex;gap:18px;flex-wrap:wrap}.site-header nav a,footer nav a,.brand{text-decoration:none}.brand{font-weight:850;letter-spacing:-.025em}.site-header nav a,footer{color:var(--muted)}main{width:min(1180px,calc(100% - 40px));margin:auto;padding-bottom:80px}.hero{padding:68px 0 78px;max-width:960px}.eyebrow{text-transform:uppercase;letter-spacing:.14em;font-size:.74rem;font-weight:850;color:var(--muted)}h1,h2{letter-spacing:-.05em;line-height:1.02;margin:.22em 0}h1{font-size:clamp(3rem,7vw,6.2rem)}h2{font-size:clamp(2rem,4vw,3.5rem)}h3{letter-spacing:-.025em}.lead{font-size:clamp(1.1rem,2vw,1.4rem);max-width:850px;color:#404040}.panel{margin:0 0 24px;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:clamp(24px,5vw,54px);box-shadow:var(--shadow)}.compact-panel h2{font-size:2rem}.section-heading{max-width:820px;margin-bottom:28px}.section-heading>p:last-child{color:var(--muted);font-size:1.03rem}.notice{border-radius:13px;padding:17px 19px;background:#ebe8e1}.privacy-note{margin-top:28px;max-width:900px}.toolbar{display:flex;align-items:end;gap:12px;margin:18px 0}.toolbar.wrap{flex-wrap:wrap}button,.button{font:inherit;border:0;border-radius:999px;background:var(--accent);color:#fff;padding:11px 18px;font-weight:800;cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;min-height:45px}.button.secondary{background:#fff;color:var(--ink);border:1px solid var(--ink)}.button.subtle{background:#eeeae2;color:var(--ink)}.button.danger,.danger{color:#761f16}.file-button{position:relative;overflow:hidden}.file-button input{position:absolute;inset:0;opacity:0;cursor:pointer}button:disabled{opacity:.5;cursor:not-allowed}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible{outline:3px solid #5b9cff;outline-offset:3px}input,select,textarea{font:inherit;width:100%;border:1px solid var(--line);border-radius:10px;background:#fbfaf7;color:var(--ink);padding:12px 14px}textarea{resize:vertical;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.86rem}.field{display:flex;flex-direction:column;gap:7px;font-weight:750}.field small,.help{color:var(--muted);font-weight:400}.inline-field{display:grid;gap:5px;min-width:min(320px,100%);font-weight:700}.status{margin:18px 0 0;padding:14px 16px;border-left:4px solid #666;background:#f3f1ec;border-radius:10px}.status.good{border-left-color:var(--good);background:#edf7f1}.status.error{border-left-color:var(--danger);background:#fff1ee}.details-box{margin-top:14px;border:1px solid var(--line);border-radius:12px;padding:13px 15px}.details-box summary{cursor:pointer;font-weight:800}.parameter-list{display:grid;grid-template-columns:minmax(180px,.45fr) minmax(0,1fr);margin:15px 0 0}.parameter-list div{display:contents}.parameter-list dt,.parameter-list dd{padding:8px 10px;margin:0;border-top:1px solid var(--line);overflow-wrap:anywhere}.parameter-list dt{font-weight:750}.profile-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.profile-grid label{display:flex;flex-direction:column;gap:6px;font-weight:700}.wide{grid-column:1/-1}.subsection{border:1px solid var(--line);border-radius:14px;padding:18px;background:#fbfaf7}.subsection h3{font-size:1rem;margin:0 0 13px}.subsection h3 span{font-size:.76rem;font-weight:650;color:var(--muted);margin-left:5px}.profile-grid.nested{margin:0}.url-grid{display:grid;grid-template-columns:minmax(0,1fr) 180px;gap:16px;align-items:end;margin-bottom:16px}.url-grid label{display:flex;flex-direction:column;gap:6px;font-weight:700}.counter-card{min-height:73px;border:1px solid var(--line);border-radius:12px;padding:10px 15px;display:flex;align-items:baseline;justify-content:center;gap:8px;background:#fbfaf7}.counter-card strong{font-size:1.7rem}.counter-card span{color:var(--muted);font-size:.85rem}.messages{display:grid;gap:8px;margin-top:12px}.message{padding:10px 13px;border-radius:9px;background:#fff4e5;border-left:4px solid var(--warn);font-size:.9rem}.message.error{background:#fff0ed;border-left-color:var(--danger)}.message.info{background:#eef4ff;border-left-color:#4f6f9f}.result-table-wrap{overflow:auto;border:1px solid var(--line);border-radius:14px}.result-table{width:100%;border-collapse:collapse;min-width:680px}.result-table th,.result-table td{padding:14px 16px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}.result-table th{font-size:.75rem;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);background:#f7f5f0}.result-table tbody tr:last-child td{border-bottom:0}.result-table code{overflow-wrap:anywhere}.ok{color:var(--good);font-weight:800}.failed{color:var(--danger);font-weight:800}.result-links{display:flex;gap:10px;flex-wrap:wrap}.result-links a{font-size:.86rem;font-weight:750}.output-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-top:22px}.output-grid label{display:flex;flex-direction:column;gap:6px;font-weight:750}.output-grid textarea{min-height:210px}.plain-list{display:grid;gap:8px;padding-left:1.2rem}.help code{background:#eeeae2;padding:2px 5px;border-radius:5px}footer{border-top:1px solid var(--line)} +*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--bg);color:var(--ink);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;line-height:1.55}a{color:inherit}.site-header,footer{width:min(1180px,calc(100% - 40px));margin:auto;padding:24px 0;display:flex;align-items:center;justify-content:space-between;gap:24px}.site-header nav,footer nav{display:flex;gap:18px;flex-wrap:wrap}.site-header nav a,footer nav a,.brand{text-decoration:none}.brand{font-weight:850;letter-spacing:-.025em}.site-header nav a,footer{color:var(--muted)}main{width:min(1180px,calc(100% - 40px));margin:auto;padding-bottom:80px}.hero{padding:68px 0 78px;max-width:960px}.eyebrow{text-transform:uppercase;letter-spacing:.14em;font-size:.74rem;font-weight:850;color:var(--muted)}h1,h2{letter-spacing:-.05em;line-height:1.02;margin:.22em 0}h1{font-size:clamp(3rem,7vw,6.2rem)}h2{font-size:clamp(2rem,4vw,3.5rem)}h3{letter-spacing:-.025em}.lead{font-size:clamp(1.1rem,2vw,1.4rem);max-width:850px;color:#404040}.panel{margin:0 0 24px;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:clamp(24px,5vw,54px);box-shadow:var(--shadow)}.compact-panel h2{font-size:2rem}.section-heading{max-width:820px;margin-bottom:28px}.section-heading>p:last-child{color:var(--muted);font-size:1.03rem}.notice{border-radius:13px;padding:17px 19px;background:#ebe8e1}.privacy-note{margin-top:28px;max-width:900px}.toolbar{display:flex;align-items:end;gap:12px;margin:18px 0}.toolbar.wrap{flex-wrap:wrap}button,.button{font:inherit;border:0;border-radius:999px;background:var(--accent);color:#fff;padding:11px 18px;font-weight:800;cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;min-height:45px}.button.secondary{background:#fff;color:var(--ink);border:1px solid var(--ink)}.button.subtle{background:#eeeae2;color:var(--ink)}.button.danger,.danger{color:#761f16}.file-button{position:relative;overflow:hidden}.file-button input{position:absolute;inset:0;opacity:0;cursor:pointer}button:disabled{opacity:.5;cursor:not-allowed}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible{outline:3px solid #5b9cff;outline-offset:3px}input,select,textarea{font:inherit;width:100%;border:1px solid var(--line);border-radius:10px;background:#fbfaf7;color:var(--ink);padding:12px 14px}textarea{resize:vertical;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.86rem}.field{display:flex;flex-direction:column;gap:7px;font-weight:750}.field small,.help{color:var(--muted);font-weight:400}.inline-field{display:grid;gap:5px;min-width:min(320px,100%);font-weight:700}.status{margin:18px 0 0;padding:14px 16px;border-left:4px solid #666;background:#f3f1ec;border-radius:10px}.status.good{border-left-color:var(--good);background:#edf7f1}.status.error{border-left-color:var(--danger);background:#fff1ee}.details-box{margin-top:14px;border:1px solid var(--line);border-radius:12px;padding:13px 15px}.details-box summary{cursor:pointer;font-weight:800}.parameter-list{display:grid;grid-template-columns:minmax(180px,.45fr) minmax(0,1fr);margin:15px 0 0}.parameter-list div{display:contents}.parameter-list dt,.parameter-list dd{padding:8px 10px;margin:0;border-top:1px solid var(--line);overflow-wrap:anywhere}.parameter-list dt{font-weight:750}.profile-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}.profile-grid label{display:flex;flex-direction:column;gap:6px;font-weight:700}.wide{grid-column:1/-1}.subsection{border:1px solid var(--line);border-radius:14px;padding:18px;background:#fbfaf7}.subsection h3{font-size:1rem;margin:0 0 13px}.subsection h3 span{font-size:.76rem;font-weight:650;color:var(--muted);margin-left:5px}.profile-grid.nested{margin:0}.url-grid{display:grid;grid-template-columns:minmax(0,1fr) 180px;gap:16px;align-items:end;margin-bottom:16px}.url-grid label{display:flex;flex-direction:column;gap:6px;font-weight:700}.counter-card{min-height:73px;border:1px solid var(--line);border-radius:12px;padding:10px 15px;display:flex;align-items:baseline;justify-content:center;gap:8px;background:#fbfaf7}.counter-card strong{font-size:1.7rem}.counter-card span{color:var(--muted);font-size:.85rem}.messages{display:grid;gap:8px;margin-top:12px}.message{padding:10px 13px;border-radius:9px;background:#fff4e5;border-left:4px solid var(--warn);font-size:.9rem}.message.error{background:#fff0ed;border-left-color:var(--danger)}.message.info{background:#eef4ff;border-left-color:#4f6f9f}.result-table-wrap{overflow:auto;border:1px solid var(--line);border-radius:14px}.result-table{width:100%;border-collapse:collapse;min-width:980px}.result-table th,.result-table td{padding:14px 16px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}.result-table th{font-size:.75rem;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);background:#f7f5f0}.result-table tbody tr:last-child td{border-bottom:0}.result-table code{overflow-wrap:anywhere}.ok{color:var(--good);font-weight:800}.failed{color:var(--danger);font-weight:800}.result-links{display:flex;gap:10px;flex-wrap:wrap}.result-links a{font-size:.86rem;font-weight:750}.output-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-top:22px}.output-grid label{display:flex;flex-direction:column;gap:6px;font-weight:750}.output-grid textarea{min-height:210px}.plain-list{display:grid;gap:8px;padding-left:1.2rem}.help code{background:#eeeae2;padding:2px 5px;border-radius:5px}footer{border-top:1px solid var(--line)} @media(max-width:760px){.site-header nav{display:none}.profile-grid,.url-grid,.output-grid{grid-template-columns:1fr}.wide{grid-column:auto}.toolbar{align-items:stretch}.toolbar>*{width:100%}.inline-field{min-width:0}.parameter-list{grid-template-columns:1fr}.parameter-list div{display:block;border-top:1px solid var(--line)}.parameter-list dt,.parameter-list dd{border:0;padding:4px 0}footer{align-items:flex-start;flex-direction:column}.hero{padding-top:44px}h1{font-size:3.2rem}} .embed-note{margin:14px 0 0;padding:13px 15px;border-left:4px solid #4f6f9f;border-radius:10px;background:#eef4ff;color:#31445e;font-size:.92rem;line-height:1.55} + +.bulk-disclosure-preview{margin:0}.bulk-disclosure-preview__link{display:inline-flex;align-items:center;gap:.5rem;min-height:36px;padding:.25rem .375rem;max-width:100%;color:inherit;text-decoration:underline;text-underline-offset:.15em}.bulk-disclosure-preview__badge{height:20px;width:auto;max-width:100%;flex:0 0 auto}.bulk-disclosure-preview__text{line-height:1.35;min-width:11rem}.result-table td:nth-child(2){min-width:320px} diff --git a/bulkweb/static/bulk.js b/bulkweb/static/bulk.js index ae98649..7775fc7 100644 --- a/bulkweb/static/bulk.js +++ b/bulkweb/static/bulk.js @@ -311,6 +311,30 @@ return {html, markdown, json, jsonl, csv}; } + function buildDisclosurePreview(data) { + const wrap = document.createElement('p'); + wrap.className = 'bulk-disclosure-preview'; + const link = document.createElement('a'); + link.className = 'bulk-disclosure-preview__link'; + link.href = data.declarationUrl; + link.target = '_blank'; + link.rel = 'noopener'; + + const badge = document.createElement('img'); + badge.className = 'bulk-disclosure-preview__badge'; + badge.src = data.badgeUrl; + badge.alt = ''; + badge.setAttribute('aria-hidden', 'true'); + + const text = document.createElement('span'); + text.className = 'bulk-disclosure-preview__text'; + text.textContent = data.accessibleText || 'KI-Nutzung – Details zur Kennzeichnung'; + + link.append(badge, text); + wrap.appendChild(link); + return wrap; + } + function renderResults(results) { currentResults = results; exportsCache = buildExports(results); @@ -326,14 +350,16 @@ const code = document.createElement('code'); code.textContent = item.subject; subjectCell.appendChild(code); + const previewCell = document.createElement('td'); const statusCell = document.createElement('td'); statusCell.className = item.ok ? 'ok' : 'failed'; statusCell.textContent = item.ok ? '✓ erzeugt' : `Fehler: ${item.error || 'unbekannt'}`; const linksCell = document.createElement('td'); if (item.ok && item.data) { + previewCell.appendChild(buildDisclosurePreview(item.data)); const links = document.createElement('div'); links.className = 'result-links'; - [['Declaration', item.data.declarationUrl], ['JSON-LD', item.data.manifestUrl], ['Badge', item.data.badgeUrl]].forEach(([label, href]) => { + [['Declaration', item.data.declarationUrl], ['JSON-LD', item.data.manifestUrl], ['SVG (nur Grafik)', item.data.badgeUrl]].forEach(([label, href]) => { const a = document.createElement('a'); a.textContent = label; a.href = href; @@ -343,7 +369,7 @@ }); linksCell.appendChild(links); } - tr.append(subjectCell, statusCell, linksCell); + tr.append(subjectCell, previewCell, statusCell, linksCell); tbody.appendChild(tr); }); $('output-html').value = exportsCache.html; diff --git a/bulkweb/templates/index.html b/bulkweb/templates/index.html index b40337a..a573ecd 100644 --- a/bulkweb/templates/index.html +++ b/bulkweb/templates/index.html @@ -211,11 +211,11 @@ -

Der HTML-Export ist die empfohlene Ein-Schritt-Integration: sichtbarer, tastaturerreichbarer Hinweis mit Text neben dem Badge plus eingebettetes JSON-LD. Das SVG ist dabei dekorativ; die zugängliche Bezeichnung stammt aus dem sichtbaren Linktext.

+

Der HTML-Export ist die empfohlene Ein-Schritt-Integration: sichtbarer, tastaturerreichbarer Hinweis mit Text neben dem Badge plus eingebettetes JSON-LD. Die Vorschau unten zeigt genau diese sichtbare Kennzeichnung. Der Link „SVG (nur Grafik)“ dient nur zum separaten Abruf der Bilddatei und ist nicht die empfohlene alleinstehende Integration.

- +
InhaltStatusLinks
InhaltKennzeichnungStatusLinks
diff --git a/deploy/kubernetes.yaml b/deploy/kubernetes.yaml index 54c4456..a2e0aea 100644 --- a/deploy/kubernetes.yaml +++ b/deploy/kubernetes.yaml @@ -25,7 +25,7 @@ spec: type: RuntimeDefault containers: - name: app - image: ghcr.io/REPLACE_ME/ai-disclosure-standard:1.8.1 + image: ghcr.io/REPLACE_ME/ai-disclosure-standard:1.8.2 imagePullPolicy: IfNotPresent ports: - name: http diff --git a/deploy/swarm-stack.yaml b/deploy/swarm-stack.yaml index 7a30031..e66b5a2 100644 --- a/deploy/swarm-stack.yaml +++ b/deploy/swarm-stack.yaml @@ -1,7 +1,7 @@ version: "3.9" services: app: - image: ghcr.io/REPLACE_ME/ai-disclosure-standard:1.8.1 + image: ghcr.io/REPLACE_ME/ai-disclosure-standard:1.8.2 environment: BASE_URL: https://ai.example.org PUBLIC_NAME: AI Usage Disclosure diff --git a/docs/BACKGROUND-PAGE.md b/docs/BACKGROUND-PAGE.md index d38c2e8..40dd69c 100644 --- a/docs/BACKGROUND-PAGE.md +++ b/docs/BACKGROUND-PAGE.md @@ -1,6 +1,6 @@ # Mehrsprachige Hintergrundseite -Version 1.8.1 stellt unter `/background` eine eigenständige Informationsseite zur KI-Kennzeichnung und zu Artikel 50 des EU AI Act bereit. +Version 1.8.2 stellt unter `/background` eine eigenständige Informationsseite zur KI-Kennzeichnung und zu Artikel 50 des EU AI Act bereit. ## Routen diff --git a/docs/LICENSE-CLIENT.md b/docs/LICENSE-CLIENT.md index 08b142e..911f664 100644 --- a/docs/LICENSE-CLIENT.md +++ b/docs/LICENSE-CLIENT.md @@ -16,7 +16,7 @@ Initialization is performed in `internal/app/server.go`. The product ID and embe ```go licenses := licenseclient.New(ctx, licenseclient.Config{ Product: "ai-disclosure-standard", - ClientVersion: "1.8.1", + ClientVersion: "1.8.2", Token: cfg.LicenseToken, TrustStore: trustStore, BaseURL: cfg.BaseURL, diff --git a/docs/LICENSE-INTEGRATION.md b/docs/LICENSE-INTEGRATION.md index 2108cc3..690c9fe 100644 --- a/docs/LICENSE-INTEGRATION.md +++ b/docs/LICENSE-INTEGRATION.md @@ -119,7 +119,7 @@ Anfrage: "baseUrl": "https://ai.example.org", "host": "ai.example.org", "instanceId": "production-eu-1", - "clientVersion": "1.8.1" + "clientVersion": "1.8.2" } ``` diff --git a/internal/app/licensing.go b/internal/app/licensing.go index 506c1e4..750a2ab 100644 --- a/internal/app/licensing.go +++ b/internal/app/licensing.go @@ -9,7 +9,7 @@ import ( const ( ProductID = "ai-disclosure-standard" - ProductVersion = "1.8.1" + ProductVersion = "1.8.2" FeatureCustomText = "custom_text" FeatureCustomBadge = "custom_badge" FeatureWhiteLabel = "white_label" diff --git a/internal/bulk/server.go b/internal/bulk/server.go index 44a337d..38973ed 100644 --- a/internal/bulk/server.go +++ b/internal/bulk/server.go @@ -18,7 +18,7 @@ import ( bulkweb "github.com/b1tsblog/ai-disclosure-standard/bulkweb" ) -const Version = "1.0.1" +const Version = "1.0.2" type Server struct { cfg Config diff --git a/internal/bulk/server_test.go b/internal/bulk/server_test.go index bf671d7..942d4d0 100644 --- a/internal/bulk/server_test.go +++ b/internal/bulk/server_test.go @@ -123,3 +123,37 @@ func TestRenderBatchHonoursConfiguredLimit(t *testing.T) { t.Fatalf("status %d: %s", w.Code, w.Body.String()) } } + +func TestBulkUIUsesAccessibleDisclosurePreview(t *testing.T) { + h, err := New(Config{ + ListenAddress: ":0", CoreInternalURL: "http://127.0.0.1:9", + DisclosureBaseURL: "https://public.example", GeneratorURL: "https://public.example", + PublicName: "Bulk", MaxURLs: 10, Workers: 1, RequestTimeout: time.Second, + }, testLogger()) + if err != nil { + t.Fatal(err) + } + + indexReq := httptest.NewRequest(http.MethodGet, "/", nil) + indexRes := httptest.NewRecorder() + h.ServeHTTP(indexRes, indexReq) + if indexRes.Code != http.StatusOK { + t.Fatalf("index status %d: %s", indexRes.Code, indexRes.Body.String()) + } + if !strings.Contains(indexRes.Body.String(), "Kennzeichnung") { + t.Fatalf("bulk result table does not expose the disclosure preview column") + } + + jsReq := httptest.NewRequest(http.MethodGet, "/static/bulk.js", nil) + jsRes := httptest.NewRecorder() + h.ServeHTTP(jsRes, jsReq) + if jsRes.Code != http.StatusOK { + t.Fatalf("bulk.js status %d: %s", jsRes.Code, jsRes.Body.String()) + } + body := jsRes.Body.String() + for _, required := range []string{"buildDisclosurePreview", "accessibleText", "SVG (nur Grafik)"} { + if !strings.Contains(body, required) { + t.Fatalf("bulk.js missing accessible preview marker %q", required) + } + } +} diff --git a/internal/marketing/content.go b/internal/marketing/content.go index bf74f27..12b479a 100644 --- a/internal/marketing/content.go +++ b/internal/marketing/content.go @@ -183,13 +183,13 @@ func Build(lang, productName, baseURL, salesURL, contactURL string, prices Price # Adjust BASE_URL and PUBLIC_NAME in .env docker compose up -d --build curl -fsS http://localhost:8080/readyz`}, - {ID: "docker", Title: copy.InstallTitles[1], Summary: copy.InstallSummaries[1], Code: `docker build -t ai-disclosure-standard:1.8.1 . + {ID: "docker", Title: copy.InstallTitles[1], Summary: copy.InstallSummaries[1], Code: `docker build -t ai-disclosure-standard:1.8.2 . docker run -d --name ai-disclosure \ -p 8080:8080 \ -e BASE_URL=https://ai.example.org \ -e PUBLIC_NAME="AI Usage Disclosure" \ --read-only --tmpfs /tmp \ - ai-disclosure-standard:1.8.1`}, + ai-disclosure-standard:1.8.2`}, {ID: "kubernetes", Title: copy.InstallTitles[2], Summary: copy.InstallSummaries[2], Code: `# Image, Domain und TLS-Secret in deploy/kubernetes.yaml ersetzen kubectl create secret generic ai-disclosure-license \ --from-literal=token='...' diff --git a/openapi.yaml b/openapi.yaml index 4d41548..b62cf2e 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: AI Usage Disclosure API - version: 1.8.1 + version: 1.8.2 description: Stateless multilingual badge, declaration and validation API with optional licensed presentation capabilities. servers: - url: https://ai.example.org diff --git a/web/templates/background.html b/web/templates/background.html index 99d6452..c678b83 100644 --- a/web/templates/background.html +++ b/web/templates/background.html @@ -158,7 +158,7 @@ - + diff --git a/web/templates/index.html b/web/templates/index.html index 226597d..2d4e2ae 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -290,7 +290,7 @@

HA

{{index .Text "api_stateless_title"}}

{{index .Text "api_stateless_desc"}}

- + diff --git a/web/templates/marketing.html b/web/templates/marketing.html index 79bc516..6bcbbc3 100644 --- a/web/templates/marketing.html +++ b/web/templates/marketing.html @@ -119,7 +119,7 @@ - +