feat: expand opt-in capability coverage with versioned consent

This commit is contained in:
Paul Nothaft
2026-09-06 00:56:58 +02:00
parent 5d31b61c8d
commit a7382591bf
32 changed files with 6250 additions and 164 deletions
@@ -0,0 +1,35 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import catalog from './usageFeatures.v2.json';
/** Local, static disclosure: opening it never contacts the collector. */
export function UsageCatalog() {
const { t } = useTranslation();
const [search, setSearch] = useState('');
const entries = Object.entries(catalog.features).filter(([key]) =>
`${key} ${t(`productUsage.catalog.${key}.name`)}`.toLowerCase().includes(search.toLowerCase()));
return (
<details className="rounded border border-theme p-3">
<summary className="cursor-pointer font-semibold">{t('productUsage.catalogTitle')}</summary>
<p className="my-3 text-sm">{t('productUsage.catalogExplanation')}</p>
<label className="block text-sm">
{t('productUsage.catalogSearch')}
<input type="search" value={search} onChange={(e) => setSearch(e.target.value)}
className="my-2 w-full rounded border border-theme bg-theme-surface p-2" />
</label>
<div className="max-h-96 space-y-3 overflow-y-auto" tabIndex={0}>
{entries.map(([key, definition]) => (
<section key={key} className="border-t border-theme pt-2">
<h4 className="font-semibold">{t(`productUsage.catalog.${key}.name`)}</h4>
<p className="text-xs"><code>{key}</code> · {definition.since}</p>
<p className="text-sm">{t('productUsage.configuredLabel')}: {t(`productUsage.catalog.${key}.configured`)}</p>
<p className="text-sm">{definition.used
? `${t('productUsage.usedLabel')}: ${t(`productUsage.catalog.${key}.used`)}`
: t('productUsage.configurationOnly')}</p>
</section>
))}
{!entries.length && <p>{t('productUsage.catalogEmpty')}</p>}
</div>
</details>
);
}
@@ -3,7 +3,8 @@ import {
screen,
fireEvent,
waitFor,
cleanup
cleanup,
within
} from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { beforeEach, afterEach, describe, it, expect, vi } from 'vitest';
@@ -27,6 +28,7 @@ vi.mock('../../../services/productUsage.service', () => ({
productUsageService: {
status: vi.fn(),
enable: vi.fn(),
upgradeConsent: vi.fn(),
disable: vi.fn(),
retry: vi.fn(),
preview: vi.fn(),
@@ -66,6 +68,40 @@ beforeEach(() => {
};
});
afterEach(cleanup);
it('shows every v2 signal locally before participation, without collector calls', async () => {
mount();
await screen.findByText('productUsage.catalogTitle');
expect(screen.getAllByRole('heading', { level: 4, hidden: true })).toHaveLength(73);
expect(service.enable).not.toHaveBeenCalled();
expect(service.preview).not.toHaveBeenCalled();
expect(service.upgradeConsent).not.toHaveBeenCalled();
});
it('existing v1 requires renewed unchecked consent; cancellation keeps v1 unchanged', async () => {
vi.mocked(service.status).mockResolvedValue({ ...status, status: 'active', consent_update_available: true });
vi.mocked(service.upgradeConsent).mockResolvedValue({ delivered: false, queued: true, state: { ...status, status: 'active', pending_action: 'consent' } });
mount();
fireEvent.click(await screen.findByText('productUsage.reviewUpgrade'));
let dialog = within(screen.getByRole('dialog'));
expect(dialog.getByRole('button', { name: 'productUsage.upgrade' })).toBeDisabled();
expect(dialog.getByRole('checkbox')).not.toBeChecked();
expect(dialog.getByText('productUsage.versionDisclosure')).toBeInTheDocument();
fireEvent.click(dialog.getByRole('button', { name: 'productUsage.cancel' }));
expect(service.upgradeConsent).not.toHaveBeenCalled();
fireEvent.click(screen.getByText('productUsage.reviewUpgrade'));
dialog = within(screen.getByRole('dialog'));
fireEvent.click(dialog.getByRole('checkbox'));
fireEvent.click(dialog.getByRole('button', { name: 'productUsage.upgrade' }));
await waitFor(() => expect(service.upgradeConsent).toHaveBeenCalledTimes(1));
expect(service.enable).not.toHaveBeenCalled();
expect(await screen.findByText('productUsage.queued')).toBeInTheDocument();
});
it('pending v2 confirmation clearly keeps v1 and cannot queue another upgrade', async () => {
vi.mocked(service.status).mockResolvedValue({ ...status, status: 'active', consent_update_available: true, pending_action: 'consent' });
mount();
expect(await screen.findByText('productUsage.upgradePending')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'productUsage.reviewUpgrade' })).toBeDisabled();
expect(service.upgradeConsent).not.toHaveBeenCalled();
});
describe('product usage controls', () => {
it('offers identity-free audit receipts after opt-out without restoring participation controls', async () => {
vi.mocked(service.status).mockResolvedValue({
@@ -16,6 +16,7 @@ import {
} from 'lucide-react';
import { useConfirm } from '../../../components/common/ConfirmDialog';
import { Button, Card } from '../../../components/common';
import { UsageCatalog } from '../UsageCatalog';
/**
* Sections of the disclosure, in reading order. Each is a translated
@@ -39,12 +40,14 @@ function ConsentDialog({
close,
enable,
busy,
collector
collector,
upgrade = false
}: {
close: () => void;
enable: () => void;
busy: boolean;
collector: string;
upgrade?: boolean;
}) {
const { t } = useTranslation();
const ref = useRef<HTMLDialogElement>(null);
@@ -112,6 +115,8 @@ function ConsentDialog({
</p>
</section>
))}
<p className="text-sm">{t('productUsage.versionDisclosure')}</p>
<UsageCatalog />
<div className="flex flex-wrap gap-x-6 gap-y-1 pt-1 text-sm">
<a
@@ -148,7 +153,7 @@ function ConsentDialog({
{t('productUsage.cancel')}
</Button>
<Button onClick={enable} disabled={!checked || busy}>
{t('productUsage.enable')}
{t(upgrade ? 'productUsage.upgrade' : 'productUsage.enable')}
</Button>
</div>
</footer>
@@ -212,6 +217,16 @@ export default function ProductUsageTab() {
{t(`productUsage.states.${data.status}`)}
</h3>
<p>{t(`productUsage.stateDetails.${data.status}`)}</p>
{data.status !== 'disabled' && <p>{t('productUsage.currentSchema', { schema: data.schema_version })}</p>}
{data.consent_update_available && (
<div className="rounded border border-theme p-3 space-y-2">
<p>{t('productUsage.upgradeExplanation')}</p>
<Button disabled={busy || Boolean(data.pending_action) || !data.collector_url} onClick={() => setConsent(true)}>
{t('productUsage.reviewUpgrade')}
</Button>
</div>
)}
{data.pending_action === 'consent' && <p role="status">{t('productUsage.upgradePending')}</p>}
{data.installation_id && (
<label className="block">
{t('productUsage.hash')}
@@ -300,6 +315,7 @@ export default function ProductUsageTab() {
)}
</div>
</Card>
<UsageCatalog />
{data.privacy_receipts &&
Object.keys(data.privacy_receipts).length > 0 && (
<Card padding="md" className="space-y-4">
@@ -549,12 +565,17 @@ export default function ProductUsageTab() {
{message && <p role="status">{message}</p>}
{consent && (
<ConsentDialog
upgrade={active}
collector={data.collector_url ?? ''}
busy={busy}
close={() => setConsent(false)}
enable={() =>
run(async () => {
await service.enable();
if (active) {
const result = await service.upgradeConsent();
if (!result.delivered) setMessage(t('productUsage.queued'));
setPreview(null);
} else await service.enable();
setConsent(false);
})
}
File diff suppressed because it is too large Load Diff
+364 -1
View File
@@ -1,5 +1,369 @@
{
"productUsage": {
"fields": "usage.v2-Berichte enthalten einen Installationsfingerabdruck, PicPeak-Version, UTC-Berichtstag und Erstellungszeit, Schema-/Signaturmetadaten, feste Galerie-Layouts und 73 fest definierte Funktionssignale: 56 Konfiguriert/Genutzt-Paare und 17 reine Konfigurationswerte. Der vollständige Katalog unten erklärt jedes Feld. Keine Aktionsanzahlen und keine Besucherbeobachtung.",
"catalogTitle": "Vollständiger Katalog: alle 73 Funktionssignale (usage.v2)",
"catalogExplanation": "Konfiguriert beschreibt technische Verfügbarkeit oder Konfiguration, nicht Beliebtheit. Integrierte Funktionen sind immer verfügbar. Genutzt ist ein einziges installationsweites Ja/Nein seit Zustimmung zum aktuellen Schema (v1: seit Teilnahme; v2: seit Teilnahme oder ausdrücklicher Erweiterung). Angenommene Aufträge gelten als gestartet, nicht zwingend abgeschlossen. Reine Konfigurationssignale haben kein Genutzt-Feld. Die Marker speichern weder Person noch Ereignis-ID, Aktionszeit oder Häufigkeit.",
"catalogSearch": "Funktionsname oder Schlüssel suchen",
"catalogEmpty": "Keine passenden Funktionen.",
"configuredLabel": "Konfiguriert",
"usedLabel": "Genutzt",
"configurationOnly": "Nur Konfiguration — tatsächliche Nutzung wird nicht erfasst.",
"versionDisclosure": "Diese Zustimmung gilt für usage.v2 / usage-consent.v2. Bestehende v1-Teilnehmer teilen weiterhin nur die bisherigen 19 Funktionen, bis sie der Erweiterung ausdrücklich zustimmen. Vertrauliche Identität und Rohberichtshistorie bleiben erhalten; der lokale Beobachtungszeitraum der Nutzungsmarker beginnt mit der Collector-Bestätigung neu. Pro UTC-Tag wird höchstens ein Bericht angenommen; der erste v2-Bericht kann daher am nächsten aktiven Tag erfolgen. Vor Bestätigung werden keine neuen lokalen Marker erfasst.",
"currentSchema": "Aktuelles Berichtsschema: {{schema}}",
"reviewUpgrade": "Erweiterten Umfang von usage.v2 prüfen",
"upgrade": "usage.v2 ausdrücklich zustimmen",
"upgradeExplanation": "Deine bestehende usage.v1-Teilnahme bleibt unverändert. Prüfe den vollständigen erweiterten Katalog, bevor du über das Upgrade entscheidest. Eine Ablehnung beendet deine bisherige Teilnahme nicht.",
"upgradePending": "Die signierte Erweiterung der Zustimmung wartet auf Bestätigung. Es wird nur der bisherige v1-Umfang erfasst. Versuche es erneut, sobald der Collector erreichbar ist, oder deaktiviere die Teilnahme zum Stoppen und Löschen.",
"catalog": {
"crm": {
"name": "Kundenverwaltung",
"configured": "Der Funktionsschalter clients ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"crm_quotes": {
"name": "Angebote",
"configured": "Der Funktionsschalter quotes ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"crm_invoices": {
"name": "Rechnungen",
"configured": "Der Funktionsschalter bills ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"crm_contracts": {
"name": "Verträge",
"configured": "Der Funktionsschalter contracts ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"crm_projects": {
"name": "Projekte",
"configured": "Der Funktionsschalter projects ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"crm_calendar": {
"name": "Admin-Kalender",
"configured": "Der Funktionsschalter calendar ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"crm_hours": {
"name": "Zeiterfassung",
"configured": "Der Funktionsschalter hoursLogging ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"customer_portal": {
"name": "Kundenportal",
"configured": "Der Funktionsschalter customerPortal ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"accounting": {
"name": "Buchhaltung",
"configured": "Der Funktionsschalter accounting ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"workflows": {
"name": "Workflows",
"configured": "Der Funktionsschalter workflows ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"newsletters": {
"name": "Newsletter",
"configured": "Der Funktionsschalter newsletters ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"face_recognition": {
"name": "Gesichtserkennung",
"configured": "Der Funktionsschalter faces ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"custom_css": {
"name": "Eigenes CSS",
"configured": "Eigenes CSS ist global oder über Galerie/Theme/Vorlage eingerichtet; CSS-Inhalte werden nicht gesendet.",
"used": "Angewendetes CSS nach Zustimmung festgestellt, ohne Besucher zu beobachten."
},
"oauth": {
"name": "Admin-SSO",
"configured": "Admin-OIDC ist aktiviert und die Anbieter-/Client-Konfiguration vorhanden; keine Anbieter- oder Zugangsdaten.",
"used": "Erfolgreiche Admin-SSO-Anmeldung; keine Konto-, Anbieter- oder Sitzungsdetails."
},
"smtp": {
"name": "SMTP-Versand",
"configured": "Ein ausgehender SMTP-Host ist konfiguriert; keine Hosts, Konten, Adressen oder Zugangsdaten.",
"used": "Erfolgreicher ausdrücklich ausgelöster Admin-SMTP-Test/-Versand; keine Empfänger oder Nachrichten."
},
"whatsapp": {
"name": "WhatsApp-Integration",
"configured": "Die WhatsApp-Funktion ist aktiviert und eine nutzbare Konfiguration vorhanden; keine Telefonnummer, Tokens oder Vorlagen.",
"used": "Erfolgreicher Admin-Integrationstest; keine Empfänger, Nachrichten oder Zustellverläufe."
},
"backup": {
"name": "Sicherungen",
"configured": "Ein Voll- oder Datenbanksicherungsplan ist aktiviert; keine Zeitpläne, Pfade, Speichergrößen oder Sicherungsnamen.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"s3_storage": {
"name": "S3-Speicher",
"configured": "S3 ist für Medien oder Sicherungen konfiguriert; keine Buckets, Endpunkte, Zugangsdaten oder Objektschlüssel.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"share_mounts": {
"name": "Externe Ordner",
"configured": "Mindestens eine Galerie verwendet einen externen Ordner; nur Existenz, keine Ordnerpfade oder Galeriekennungen.",
"used": "Ein Admin hat einen angenommenen Import aus einem externen Ordner ausgelöst; keine Pfade, Dateien oder Anzahlen."
},
"galleries": {
"name": "Galerieverwaltung",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"photo_management": {
"name": "Medienverwaltung",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"photo_exports": {
"name": "Admin-Medienexport",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"photo_processing": {
"name": "Medien-Wartungswerkzeuge",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"archive_management": {
"name": "Galeriearchive",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"gallery_sharing": {
"name": "Galeriefreigabe und QR",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"short_links": {
"name": "Kurzlinks",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"gallery_categories": {
"name": "Fotokategorien",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"event_types": {
"name": "Ereignistypen und Vorlagen",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"slideshow": {
"name": "Live-Diashow",
"configured": "Der Funktionsschalter slideshow ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"transfers": {
"name": "PicTransfer",
"configured": "Der Funktionsschalter transfers ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"video_uploads": {
"name": "Admin-Video-Uploads",
"configured": "Videoformate sind in den globalen Upload-Einstellungen erlaubt; keine Metadaten hochgeladener Dateien.",
"used": "Mindestens eine Admin-Videodatei wurde erfolgreich gespeichert/angenommen; keine Namen, Formate, Längen, Größen oder Verarbeitungs-/Besucherverläufe."
},
"camera_raw_uploads": {
"name": "Admin-Kamera-RAW-Uploads",
"configured": "Kamera-RAW (DNG) ist in den globalen Upload-Einstellungen erlaubt; keine Kameramodelle oder EXIF-Daten.",
"used": "Mindestens ein Admin-Kamera-RAW-Upload wurde gespeichert/angenommen; nur das Capability-Bit, keine Dateinamen oder Metadaten."
},
"messaging": {
"name": "Nachrichtenwerkzeuge",
"configured": "Der Funktionsschalter messaging ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"incoming_mail": {
"name": "IMAP-Empfang",
"configured": "Eingehende E-Mails sind aktiviert und eine IMAP-Konfiguration vorhanden; keine Postfächer, Server, Ordner oder Zugangsdaten.",
"used": "Erfolgreicher expliziter Admin-Verbindungstest oder nicht übersprungener manueller Abruf; kein Hintergrundempfang, keine Nachrichten, Anhänge oder Anzahlen."
},
"reminder_emails": {
"name": "Automatische Ereigniserinnerungen",
"configured": "Der Funktionsschalter reminderEmails ist effektiv aktiviert; nur ein Wahrheitswert."
},
"email_templates": {
"name": "E-Mail-Vorlagen",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"email_webhook": {
"name": "E-Mail-Webhook-Transport",
"configured": "Beide E-Mail-Webhook-Einstellungen sind vorhanden; keine URL oder Geheimnisse.",
"used": "Erfolgreicher ausdrücklich ausgelöster Admin-Versand/-Test über den Webhook-Transport; keine Empfänger, Nachrichten oder automatischen Zustellungen."
},
"accounting_incoming_invoices": {
"name": "Eingangsrechnungen",
"configured": "Der Funktionsschalter incomingInvoices ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"accounting_expenses": {
"name": "Ausgaben",
"configured": "Der Funktionsschalter expenses ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"accounting_tax_report": {
"name": "Steuerberichte",
"configured": "Der Funktionsschalter taxReport ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"accounting_ledger": {
"name": "Kontenplan und Buchhaltungsexport",
"configured": "Der Funktionsschalter accounting ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"crm_installments": {
"name": "Ratenplan-Werkzeuge",
"configured": "Angebote oder Rechnungen sind aktiviert; tatsächliche Ratenpläne, Beträge oder Zahlungsstatus werden nicht geprüft.",
"used": "Ein Admin hat einen Ratenplan gespeichert; keine Termine, Beträge, Währungen, Zahlungsstatus oder Dokumentkennungen."
},
"document_templates": {
"name": "Dokumentvorlagen und Bausteine",
"configured": "Angebote oder Verträge sind aktiviert und stellen Dokumentvorlagen/-bausteine bereit; keine Vorlageninhalte.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"cms": {
"name": "CMS-Seiten",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"public_site": {
"name": "Öffentliche Startseite",
"configured": "Die Einstellung für die öffentliche Startseite ist aktiviert; keine HTML-Inhalte, Texte, Domains oder Besucher."
},
"branding": {
"name": "Branding-Einstellungen",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"seo_customization": {
"name": "SEO-Einstellungen",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"admin_management": {
"name": "Admin- und Rollenverwaltung",
"configured": "Der Funktionsschalter userManagement ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"api_integration": {
"name": "HTTP-API-Integration",
"configured": "Ein nicht widerrufener und nicht abgelaufener API-Zugang existiert; keine Tokens, Namen, Berechtigungswerte oder Inhaberdaten.",
"used": "Erfolgreicher authentifizierter HTTP-API-Funktionsaufruf; nur dieses Bit, niemals URLs, Requestwerte, Token-/Inhaberkennungen oder Aufrufzahlen. Löst keinen Report aus."
},
"webhooks": {
"name": "Ausgehende Webhooks",
"configured": "Mindestens ein aktiver Webhook ist konfiguriert; keine Ziele, Abonnements, Geheimnisse oder Zustellprotokolle.",
"used": "Erfolgreicher expliziter Admin-Webhook-Test/-Replay; keine automatischen oder durch Besucher ausgelösten Zustellungen."
},
"restore": {
"name": "Wiederherstellung",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"portable_backup": {
"name": "Portabler PicPeak-Export/Import",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"database_backup": {
"name": "Datenbanksicherungen",
"configured": "Geplante Datenbanksicherungen sind aktiviert; keine Zeitpläne, Dateinamen oder Datenbankinhalte.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"s3_photo_storage": {
"name": "S3-Medienspeicher",
"configured": "S3 ist als Medienspeicher konfiguriert und erforderliche Zugangsdaten sind vorhanden; keine Werte werden gesendet.",
"used": "Erfolgreiche Admin-Medienspeicherung/angenommener Upload nach S3; keine Buckets, Objekte oder Größen."
},
"s3_backups": {
"name": "S3-Sicherungsziel",
"configured": "Das konfigurierte Sicherungsziel ist S3 und ein Bucket ist angegeben; kein Bucketname oder Zugangsdaten.",
"used": "Ein Admin hat eine Sicherung zum konfigurierten S3-Ziel oder einen erfolgreichen S3-Testupload gestartet; lokale Exporte implizieren keine S3-Nutzung."
},
"analytics_dashboard": {
"name": "Bestehendes Analytics-Modul",
"configured": "Der Funktionsschalter analytics ist effektiv aktiviert; nur ein Wahrheitswert.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"feedback_moderation": {
"name": "Feedback-Moderation",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"guest_management": {
"name": "Gastverwaltungswerkzeuge",
"configured": "Integrierte Funktion ist verfügbar; dies ist kein Nutzungsnachweis.",
"used": "Eine dokumentierte erfolgreiche authentifizierte Admin-Funktionsoperation wurde seit Zustimmung zu diesem Schema beobachtet. Keine Person, Operationshistorie, Parameter oder Anzahlen."
},
"gallery_feedback_likes": {
"name": "Galerie-Likes aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_feedback_ratings": {
"name": "Galerie-Sternebewertungen aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_feedback_comments": {
"name": "Galerie-Kommentare aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_feedback_favorites": {
"name": "Galerie-Favoriten aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_feedback_reactions": {
"name": "Galerie-Reaktionen aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_feedback_color_labels": {
"name": "Galerie-Farblabels aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_guest_accounts": {
"name": "Gastidentitäten aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_guest_uploads": {
"name": "Gast-Uploads aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_downloads": {
"name": "Galerie-Downloads erlaubt",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"download_resolution_picker": {
"name": "Download-Auflösungswahl aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_client_access": {
"name": "Client-Zugang aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_watermarks": {
"name": "Wasserzeichen aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_image_protection": {
"name": "Bildschutz aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_reveal": {
"name": "Galerie-Enthüllung aktiviert",
"configured": "In der betreffenden Galerie-/Globalkonfiguration aktiviert; nur installationsweite Existenz, niemals Galeriekennungen oder Anzahlen."
},
"gallery_expiration": {
"name": "Galerieablauf konfiguriert",
"configured": "Mindestens eine Galerie hat einen Ablauf konfiguriert; keine Daten, Galeriekennungen oder Anzahlen."
}
},
"auditTitle": "Export- und Löschquittungen",
"auditDescription": "Lade deine privaten Nachweise herunter. PicPeak speichert nur die letzte Exportquittung während der Teilnahme und die letzte Löschbestätigung. Sie enthalten keinen Installationshash, Schlüssel oder Bericht-/Feedbackinhalt. Opt-out entfernt die lokale Exportquittung; die Löschbestätigung ohne Identitätsbezug bleibt erhalten. Der Collector führt keinen Export- oder Zugriffsverlauf.",
"auditDownload": "Datenschutzquittungen herunterladen",
@@ -20,7 +384,6 @@
"sectionVisibility": "Wo er sichtbar ist",
"sectionDeletion": "Beenden und löschen",
"sectionFeedback": "Feedback ist getrennt",
"fields": "Berichte enthalten einen Installationsfingerabdruck, PicPeak-Version, Berichtstag, Schema- und Signaturmetadaten, Galerie-Layouts sowie Konfiguriert/Genutzt-Werte für CRM und Unterfunktionen, Buchhaltung, Workflows, Newsletter, Gesichtserkennung, eigenes CSS, OAuth, SMTP, WhatsApp, Backups, S3 und eingebundene Freigaben. „Genutzt“ bedeutet seit der Teilnahme beobachtet, nicht wie häufig.",
"excluded": "Automatische Berichte enthalten keine Galeriebesucher, Klickverläufe, Foto- oder Galerieanzahlen, Namen, E-Mail-Adressen, Domains, Dateinamen oder Zugangsdaten.",
"transport": "Dein PicPeak-Backend verwahrt den Signaturschlüssel und sendet einmal pro UTC-Tag bei Admin-Nutzung signierte Nutzungsberichte an {{collector}}. Du kannst Berichte vorab ansehen und jeden eindeutig angenommenen Bericht genau wie beim ersten Empfang herunterladen; Übertragungswiederholungen werden zusammengeführt. Abgelehnte Versuche und getrennt gesendetes Feedback gehören nicht zu diesem Berichtsexport.",
"visibility": "Nur teilnehmende Installationen können den Funktionsdatensatz und aggregierte Ergebnisse einsehen, auch Gruppen mit nur einer Installation. Schema und Quellcode sind öffentlich; geprüfte Funktionswünsche und Empfehlungen werden nur mit Erlaubnis ihrer Verfasser veröffentlicht. Dein Fingerabdruck ist pseudonym, nicht anonym. Bewahre deinen Abfrage-Hash vertraulich auf: Er ermöglicht lesenden Zugriff auf deine eigenen Berichte und den Teilnehmerdatensatz.",
+364 -1
View File
@@ -1,5 +1,369 @@
{
"productUsage": {
"fields": "usage.v2 reports contain an installation fingerprint, PicPeak version, UTC report date and generation time, schema/signing metadata, controlled gallery layouts, and 73 fixed capability signals: 56 configured/used pairs and 17 configuration-only booleans. The complete catalog below defines every field. There are no action counts or visitor observations.",
"catalogTitle": "Full catalog: all 73 capability signals (usage.v2)",
"catalogExplanation": "Configured describes current technical availability or configuration, not popularity. Built-in capabilities are always available. Used is a single installation-wide yes/no bit since consent to the current schema (v1: since joining; v2: since joining or explicit upgrade). Accepted jobs count as initiated, not necessarily finished. Configuration-only capabilities have no used field. No actor, event identifier, action time or frequency is stored in these markers.",
"catalogSearch": "Search capability name or key",
"catalogEmpty": "No matching capabilities.",
"configuredLabel": "Configured",
"usedLabel": "Used",
"configurationOnly": "Configuration only — actual use is not collected.",
"versionDisclosure": "This consent covers usage.v2 / usage-consent.v2. Existing v1 participants continue sharing only the previous 19 capabilities unless they explicitly upgrade. The same private identity and raw history remain; the local usage-marker observation period restarts when the collector confirms the upgrade. At most one report per UTC day is accepted, so the first v2 report can be on the next active day. New local markers are not recorded before confirmation.",
"currentSchema": "Current reporting schema: {{schema}}",
"reviewUpgrade": "Review expanded usage.v2 scope",
"upgrade": "Explicitly agree to usage.v2",
"upgradeExplanation": "Your existing usage.v1 participation is unchanged. Review the complete expanded catalog before deciding whether to upgrade. Declining does not end your current participation.",
"upgradePending": "The signed consent upgrade is pending confirmation. Only the existing v1 scope is collected. Retry when the collector is available, or disable participation to stop and delete.",
"catalog": {
"crm": {
"name": "Client management",
"configured": "The clients capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"crm_quotes": {
"name": "Quotes",
"configured": "The quotes capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"crm_invoices": {
"name": "Invoices",
"configured": "The bills capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"crm_contracts": {
"name": "Contracts",
"configured": "The contracts capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"crm_projects": {
"name": "Projects",
"configured": "The projects capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"crm_calendar": {
"name": "Admin calendar",
"configured": "The calendar capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"crm_hours": {
"name": "Hours logging",
"configured": "The hoursLogging capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"customer_portal": {
"name": "Customer portal",
"configured": "The customerPortal capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"accounting": {
"name": "Accounting",
"configured": "The accounting capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"workflows": {
"name": "Workflows",
"configured": "The workflows capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"newsletters": {
"name": "Newsletters",
"configured": "The newsletters capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"face_recognition": {
"name": "Face recognition",
"configured": "The faces capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"custom_css": {
"name": "Custom CSS",
"configured": "Custom CSS is configured globally or applied through a gallery/theme/template; CSS text is not sent.",
"used": "Applied CSS observed after consent, without observing visitors."
},
"oauth": {
"name": "Admin SSO",
"configured": "Admin OIDC is enabled and issuer/client configuration is present; no provider or credential values.",
"used": "Successful admin SSO login; no account, identity-provider or session details."
},
"smtp": {
"name": "SMTP delivery",
"configured": "An outgoing SMTP host is configured; no host, account, address or credentials.",
"used": "A successful explicitly initiated admin SMTP test/send; no recipients or messages."
},
"whatsapp": {
"name": "WhatsApp integration",
"configured": "The WhatsApp capability is enabled and a usable configuration is present; no phone number, token or template.",
"used": "Successful admin integration test; no recipient, message or delivery history."
},
"backup": {
"name": "Backups",
"configured": "A full or database backup schedule is enabled; no schedule, path, storage sizes or backup names.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"s3_storage": {
"name": "S3 storage",
"configured": "S3 is configured for media or backups; no bucket, endpoint, credentials or object keys.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"share_mounts": {
"name": "External folders",
"configured": "At least one gallery uses an external folder; only existence, no folder paths or gallery identifiers.",
"used": "An admin initiated an accepted external-folder import; no scanned paths, files or counts."
},
"galleries": {
"name": "Gallery management",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"photo_management": {
"name": "Media management",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"photo_exports": {
"name": "Admin media export",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"photo_processing": {
"name": "Media maintenance tools",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"archive_management": {
"name": "Gallery archives",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"gallery_sharing": {
"name": "Gallery sharing and QR",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"short_links": {
"name": "Short links",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"gallery_categories": {
"name": "Photo categories",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"event_types": {
"name": "Event types and presets",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"slideshow": {
"name": "Live slideshow",
"configured": "The slideshow capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"transfers": {
"name": "PicTransfer",
"configured": "The transfers capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"video_uploads": {
"name": "Admin video uploads",
"configured": "Video extensions are allowed in global upload settings; no uploaded-file metadata.",
"used": "At least one admin video file was successfully stored/accepted; no names, formats, lengths, sizes or processing/visitor history."
},
"camera_raw_uploads": {
"name": "Admin camera RAW uploads",
"configured": "Camera RAW (DNG) is allowed in global upload settings; no camera models or EXIF.",
"used": "At least one admin camera RAW upload was stored/accepted; only the capability bit, no filename or metadata."
},
"messaging": {
"name": "Messaging tools",
"configured": "The messaging capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"incoming_mail": {
"name": "IMAP intake",
"configured": "Incoming mail is enabled and an IMAP configuration is present; no mailbox, server, folders or credentials.",
"used": "A successful explicit admin connection test or non-skipped manual poll; no background intake, messages, attachments or counts."
},
"reminder_emails": {
"name": "Automatic event reminders",
"configured": "The reminderEmails capability switch is effectively enabled; only a boolean."
},
"email_templates": {
"name": "Email templates",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"email_webhook": {
"name": "Email webhook transport",
"configured": "Both email webhook settings are present; no URL or secret.",
"used": "Successful explicitly initiated admin send/test through the webhook transport; no recipients, messages or automatic deliveries."
},
"accounting_incoming_invoices": {
"name": "Incoming invoices",
"configured": "The incomingInvoices capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"accounting_expenses": {
"name": "Expenses",
"configured": "The expenses capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"accounting_tax_report": {
"name": "Tax reports",
"configured": "The taxReport capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"accounting_ledger": {
"name": "Ledger and accounting export",
"configured": "The accounting capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"crm_installments": {
"name": "Installment-plan tools",
"configured": "Quotes or invoices are enabled; no actual payment plans, amounts or statuses are inspected.",
"used": "An admin saved an installment plan; no dates, amounts, currencies, payment status or document IDs."
},
"document_templates": {
"name": "Document presets and blocks",
"configured": "Quotes or contracts are enabled, making document presets/blocks available; no template content.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"cms": {
"name": "CMS pages",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"public_site": {
"name": "Public landing page",
"configured": "The public landing-page setting is enabled; no page HTML, texts, domains or visitors."
},
"branding": {
"name": "Branding settings",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"seo_customization": {
"name": "SEO settings",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"admin_management": {
"name": "Admin and role management",
"configured": "The userManagement capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"api_integration": {
"name": "HTTP API integration",
"configured": "An unrevoked, unexpired API credential exists; no tokens, names, scopes or owner data.",
"used": "Successful authenticated HTTP API capability call; only this bit, never URLs, request values, token/owner IDs or call counts. Does not trigger a report."
},
"webhooks": {
"name": "Outbound webhooks",
"configured": "At least one active webhook is configured; no destinations, subscriptions, secrets or delivery logs.",
"used": "Successful explicit admin webhook test/replay; no automatic or visitor-triggered deliveries."
},
"restore": {
"name": "Restore",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"portable_backup": {
"name": "Portable PicPeak export/import",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"database_backup": {
"name": "Database backups",
"configured": "Scheduled database backups are enabled; no schedules, file names or database contents.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"s3_photo_storage": {
"name": "S3 media storage",
"configured": "S3 is the configured media backend and required credentials are present; no values are sent.",
"used": "Successful admin media storage/accepted upload to S3; no buckets, objects or sizes."
},
"s3_backups": {
"name": "S3 backup destination",
"configured": "The configured backup destination is S3 with a bucket present; no bucket or credentials.",
"used": "An admin started a backup to the configured S3 destination or a successful S3 test upload; local exports never imply S3 use."
},
"analytics_dashboard": {
"name": "Existing analytics module",
"configured": "The analytics capability switch is effectively enabled; only a boolean.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"feedback_moderation": {
"name": "Feedback moderation",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"guest_management": {
"name": "Guest administration tools",
"configured": "Built-in capability is available; this is not evidence of use.",
"used": "A documented successful authenticated admin capability operation was observed since consent to this schema. No actor, operation history, parameters or counts."
},
"gallery_feedback_likes": {
"name": "Gallery likes enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_feedback_ratings": {
"name": "Gallery star ratings enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_feedback_comments": {
"name": "Gallery comments enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_feedback_favorites": {
"name": "Gallery favorites enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_feedback_reactions": {
"name": "Gallery reactions enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_feedback_color_labels": {
"name": "Gallery color labels enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_guest_accounts": {
"name": "Guest identities enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_guest_uploads": {
"name": "Guest uploads enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_downloads": {
"name": "Gallery downloads allowed",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"download_resolution_picker": {
"name": "Download resolution picker enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_client_access": {
"name": "Client access enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_watermarks": {
"name": "Watermarks enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_image_protection": {
"name": "Image protection enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_reveal": {
"name": "Gallery reveal enabled",
"configured": "Enabled in applicable gallery/global configuration; only existence across the installation, never gallery IDs or counts."
},
"gallery_expiration": {
"name": "Gallery expiration configured",
"configured": "At least one gallery has an expiry configured; no dates, gallery IDs or counts."
}
},
"auditTitle": "Export and deletion receipts",
"auditDescription": "Download your private audit receipts. PicPeak keeps only the latest export receipt during participation and the latest deletion confirmation. These contain no installation hash, key or report/feedback content. Opt-out removes the local export receipt; the identity-free deletion confirmation remains. The collector does not keep an export/access history.",
"auditDownload": "Download privacy receipts",
@@ -20,7 +384,6 @@
"sectionVisibility": "Where it is visible",
"sectionDeletion": "Leaving and deleting",
"sectionFeedback": "Feedback is separate",
"fields": "Reports contain an installation fingerprint, PicPeak version, report day, schema and signing metadata, gallery layout choices, and configured/used booleans for CRM and its subfeatures, accounting, workflows, newsletters, face recognition, custom CSS, OAuth, SMTP, WhatsApp, backups, S3, and share mounts. “Used” means observed since joining, not how often.",
"excluded": "No gallery visitors, clickstreams, photo or gallery counts, names, emails, domains, filenames, or configuration secrets are included in automatic usage reports.",
"transport": "Your PicPeak backend keeps the signing key and sends signed usage reports to {{collector}} once per UTC day during admin use. Preview reports and download each unique accepted report exactly as first received; transport retries are deduplicated. Rejected attempts and separately submitted feedback are not part of this report export.",
"visibility": "Only participating installations can inspect the feature dataset and aggregate results, including groups of one. The schema and source are public; approved feature requests and testimonials are public only with their authors permission. Your fingerprint is pseudonymous, not anonymous. Keep your lookup hash private: it grants read-only access to your own reports and the participant dataset.",
@@ -12,6 +12,9 @@ export interface UsageStatus {
collector_url: string | null;
collector_error?: 'INVALID_COLLECTOR_URL' | null;
schema_version: string;
available_schema_version?: string;
consent_version?: string;
consent_update_available?: boolean;
last_report_date: string | null;
last_error: string | null;
pending_action: string | null;
@@ -40,10 +43,13 @@ export const productUsageService = {
async enable(): Promise<UsageStatus> {
return (
await api.post('/admin/usage/enable', {
consent_version: 'usage-consent.v1'
consent_version: 'usage-consent.v2'
})
).data;
},
async upgradeConsent(): Promise<{ delivered: boolean; queued: boolean; state: UsageStatus }> {
return (await api.post('/admin/usage/consent', { consent_version: 'usage-consent.v2' })).data;
},
async disable(): Promise<UsageStatus> {
return (await api.post('/admin/usage/disable')).data;
},