@app4you/cookie-banner 0.0.0-stage → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -2
- package/dist/NOTICE +20 -0
- package/dist/cookie-banner.js +1 -0
- package/dist/core/csp.d.ts +25 -0
- package/dist/core/service-consent.d.ts +4 -0
- package/dist/i18n/locale.d.ts +7 -0
- package/dist/licenses/open-cookie-database-Apache-2.0.txt +201 -0
- package/dist/licenses/third-party-web-MIT.txt +20 -0
- package/dist/native/app-CzgF6XmJ.js +1593 -0
- package/dist/native/native-B9FXlXDp.js +1503 -0
- package/dist/native.d.ts +27 -0
- package/dist/native.js +15 -0
- package/dist/types.d.ts +145 -0
- package/docs/consent-compliance.md +142 -0
- package/docs/consent-integration.md +262 -0
- package/docs/deployment-security.md +28 -0
- package/docs/multilingual.md +100 -0
- package/package.json +66 -4
package/dist/native.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ServiceDefinition } from "./types.js";
|
|
2
|
+
export { resolveLocalizedConfig } from "./i18n/locale.js";
|
|
3
|
+
export { buildConsentCsp, consentCspHeaders, readCspConsent } from "./core/csp.js";
|
|
4
|
+
export type { ConsentCspOptions, CspSources } from "./core/csp.js";
|
|
5
|
+
import type { BannerConfig, ConsentReceipt } from "./types.js";
|
|
6
|
+
export { hasServiceConsent, setServiceConsent, onServiceConsent, } from "./core/service-consent.js";
|
|
7
|
+
export type { BannerConfig, LocalizedContent, ConsentState, ServiceDefinition, ConsentCleanup, } from "./types.js";
|
|
8
|
+
/** Safe in server components/SSR: never supplies a live src. */
|
|
9
|
+
export declare function blockedContentProps(service: string, src?: string): {
|
|
10
|
+
"data-cb-service": string;
|
|
11
|
+
"data-cb-src": string | undefined;
|
|
12
|
+
hidden: boolean;
|
|
13
|
+
};
|
|
14
|
+
/** Use a native <script>, not a framework's eager script loader. */
|
|
15
|
+
export declare function blockedScriptProps(service: string, src?: string): {
|
|
16
|
+
type: string;
|
|
17
|
+
"data-cb-type": string;
|
|
18
|
+
"data-cb-service": string;
|
|
19
|
+
"data-cb-src": string | undefined;
|
|
20
|
+
hidden: boolean;
|
|
21
|
+
};
|
|
22
|
+
/** Call in a client effect. Importing this entry on the server is safe. */
|
|
23
|
+
export declare function initializeConsent(config: BannerConfig): Promise<() => void>;
|
|
24
|
+
export declare const getConsentReceipt: () => ConsentReceipt | null;
|
|
25
|
+
export type { ConsentReceipt } from "./types.js";
|
|
26
|
+
/** Current observed services, using the same registry as the consent UI and blocker. */
|
|
27
|
+
export declare function getDetectedServices(): ServiceDefinition[];
|
package/dist/native.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { B as n, E as o, F as t, G as a, H as i, I as r, J as C, K as c, L as p, M as d, y as l, s as v } from "./native/native-B9FXlXDp.js";
|
|
2
|
+
export {
|
|
3
|
+
n as blockedContentProps,
|
|
4
|
+
o as blockedScriptProps,
|
|
5
|
+
t as buildConsentCsp,
|
|
6
|
+
a as consentCspHeaders,
|
|
7
|
+
i as getConsentReceipt,
|
|
8
|
+
r as getDetectedServices,
|
|
9
|
+
C as hasServiceConsent,
|
|
10
|
+
c as initializeConsent,
|
|
11
|
+
p as onServiceConsent,
|
|
12
|
+
d as readCspConsent,
|
|
13
|
+
l as resolveLocalizedConfig,
|
|
14
|
+
v as setServiceConsent
|
|
15
|
+
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
export type ConsentCategory = "essential" | "analytics" | "marketing";
|
|
2
|
+
export type ConsentState = Record<ConsentCategory, boolean> & {
|
|
3
|
+
services?: Record<string, boolean>;
|
|
4
|
+
};
|
|
5
|
+
export type BannerMode = "gtm" | "standalone";
|
|
6
|
+
export type BannerVariant = "modal" | "bar";
|
|
7
|
+
export type BannerView = "overlay" | "preferences" | "idle";
|
|
8
|
+
export interface ScriptDef {
|
|
9
|
+
/** Optional scripts require both the category and this provider choice. */
|
|
10
|
+
service: string;
|
|
11
|
+
src?: string;
|
|
12
|
+
inline?: string;
|
|
13
|
+
async?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface ThemeConfig {
|
|
16
|
+
primary?: string;
|
|
17
|
+
/** Hover shade for primary buttons; derived from `primary` when omitted. */
|
|
18
|
+
primaryHover?: string;
|
|
19
|
+
background?: string;
|
|
20
|
+
text?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ConsentCleanup {
|
|
23
|
+
/** Exact first-party cookie names; never use wildcard deletion. */
|
|
24
|
+
cookies?: string[];
|
|
25
|
+
localStorage?: string[];
|
|
26
|
+
sessionStorage?: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface ServiceDefinition {
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
description: string;
|
|
32
|
+
privacyUrl?: string;
|
|
33
|
+
/** Reviewed retention period or criteria for this integration. */
|
|
34
|
+
retention?: string;
|
|
35
|
+
cleanup?: ConsentCleanup;
|
|
36
|
+
/** Absolute URL prefixes; matched on hostname and path, not arbitrary substrings. */
|
|
37
|
+
urls?: string[];
|
|
38
|
+
}
|
|
39
|
+
export interface ConsentReceipt {
|
|
40
|
+
id: string;
|
|
41
|
+
version: number;
|
|
42
|
+
at: number;
|
|
43
|
+
services: Record<string, boolean>;
|
|
44
|
+
categories: Record<ConsentCategory, boolean>;
|
|
45
|
+
noticeKey: string;
|
|
46
|
+
notice: {
|
|
47
|
+
lang?: string;
|
|
48
|
+
content?: Record<string, string>;
|
|
49
|
+
overlay: Record<string, string>;
|
|
50
|
+
preferences: Record<string, string | Record<ConsentCategory, {
|
|
51
|
+
label: string;
|
|
52
|
+
description: string;
|
|
53
|
+
}>>;
|
|
54
|
+
services: ServiceDefinition[];
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export interface LocalizedContent {
|
|
58
|
+
controller?: {
|
|
59
|
+
name: string;
|
|
60
|
+
contactUrl?: string;
|
|
61
|
+
};
|
|
62
|
+
purposes?: string;
|
|
63
|
+
privacyPolicyUrl?: string;
|
|
64
|
+
cookiePolicyUrl?: string;
|
|
65
|
+
customTexts?: Record<string, unknown>;
|
|
66
|
+
serviceDisclosures?: Record<string, {
|
|
67
|
+
name?: string;
|
|
68
|
+
description?: string;
|
|
69
|
+
privacyUrl?: string;
|
|
70
|
+
retention?: string;
|
|
71
|
+
}>;
|
|
72
|
+
}
|
|
73
|
+
export interface BannerConfig {
|
|
74
|
+
/** Defaults to standard in npm. WordPress defaults to equal. Never changes blocking or consent requirements. */
|
|
75
|
+
buttonStyle?: "standard" | "equal";
|
|
76
|
+
/** Per-page locale content: base language, then exact regional override. */
|
|
77
|
+
localizations?: Record<string, LocalizedContent>;
|
|
78
|
+
/** Internal isolated admin preview: memory storage, no evidence submission. */
|
|
79
|
+
preview?: boolean;
|
|
80
|
+
/** Legal identity of the website controller, not the software vendor. */
|
|
81
|
+
controller?: {
|
|
82
|
+
name: string;
|
|
83
|
+
contactUrl?: string;
|
|
84
|
+
};
|
|
85
|
+
/** Required; bump whenever policy contents, purposes or recipients change. */
|
|
86
|
+
noticeVersion?: string;
|
|
87
|
+
/** Reviewed, site-specific explanation of the requested optional processing. */
|
|
88
|
+
purposes?: string;
|
|
89
|
+
/** HTTP CSP supplied by the host; consent changes require a fresh document. */
|
|
90
|
+
strictCsp?: boolean;
|
|
91
|
+
services?: ServiceDefinition[];
|
|
92
|
+
/** Disclosure overrides for catalog providers; no duplicate blocking rules. */
|
|
93
|
+
serviceDisclosures?: Record<string, {
|
|
94
|
+
name?: string;
|
|
95
|
+
description?: string;
|
|
96
|
+
privacyUrl?: string;
|
|
97
|
+
retention?: string;
|
|
98
|
+
cleanup?: ConsentCleanup;
|
|
99
|
+
}>;
|
|
100
|
+
categoryCleanup?: Partial<Record<"analytics" | "marketing", ConsentCleanup>>;
|
|
101
|
+
/** Same-origin endpoint receiving minimal, versioned receipts (optional for native hosts). */
|
|
102
|
+
receiptEndpoint?: string;
|
|
103
|
+
receiptNonce?: string;
|
|
104
|
+
/** Early best-effort interception for third-party code. Enabled by the WP plugin. */
|
|
105
|
+
autoBlock?: boolean;
|
|
106
|
+
auditMode?: boolean;
|
|
107
|
+
mode: BannerMode;
|
|
108
|
+
variant?: BannerVariant;
|
|
109
|
+
gtmId?: string;
|
|
110
|
+
loadGtm?: boolean;
|
|
111
|
+
/** @deprecated Ignored: consent always requires a visitor action. */
|
|
112
|
+
testMode?: boolean;
|
|
113
|
+
/** @deprecated Ignored: consent always requires a visitor action. */
|
|
114
|
+
autoAcceptAll?: boolean;
|
|
115
|
+
lang: string;
|
|
116
|
+
privacyPolicyUrl?: string;
|
|
117
|
+
cookiePolicyUrl?: string;
|
|
118
|
+
theme?: ThemeConfig;
|
|
119
|
+
/** @deprecated Custom links always work; the floating withdrawal controls remain visible. */
|
|
120
|
+
useCustomSettingsLink?: boolean;
|
|
121
|
+
customTexts?: Record<string, unknown>;
|
|
122
|
+
detectedServices?: string[];
|
|
123
|
+
scripts?: {
|
|
124
|
+
analytics?: ScriptDef[];
|
|
125
|
+
marketing?: ScriptDef[];
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
export declare const STORAGE_PREFIX = "cb_consent_";
|
|
129
|
+
export declare const STORAGE_HAS_CONSENTED = "cb_has_consented";
|
|
130
|
+
export declare const STORAGE_COMMIT = "cb_consent_commit";
|
|
131
|
+
export declare const CONSENT_CATEGORIES: ConsentCategory[];
|
|
132
|
+
export declare const DEFAULT_CONSENT_STATE: ConsentState;
|
|
133
|
+
export declare const GTM_CONSENT_KEYS: readonly ["ad_storage", "analytics_storage", "ad_user_data", "ad_personalization", "functionality_storage", "security_storage", "personalization_storage"];
|
|
134
|
+
export type GTMConsentKey = (typeof GTM_CONSENT_KEYS)[number];
|
|
135
|
+
export type GTMConsentPayload = Record<GTMConsentKey, "granted" | "denied">;
|
|
136
|
+
export declare const DEFAULT_GTM_CONSENT_DENIED: GTMConsentPayload;
|
|
137
|
+
export declare const GTM_CONSENT_MAP: Record<ConsentCategory, readonly GTMConsentKey[]>;
|
|
138
|
+
declare global {
|
|
139
|
+
interface Window {
|
|
140
|
+
__cookieConsent?: BannerConfig;
|
|
141
|
+
dataLayer?: any[];
|
|
142
|
+
gtag?: (...args: unknown[]) => void;
|
|
143
|
+
fbq?: (...args: unknown[]) => void;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Konfiguracja zgód i informacji o prywatności
|
|
2
|
+
|
|
3
|
+
Baner nie uruchamia opcjonalnego przetwarzania,
|
|
4
|
+
jeżeli brakuje danych administratora, celu, wersji informacji lub poprawnego linku
|
|
5
|
+
do polityki prywatności. Stare rekordy zgody są unieważniane. Odmowa działa także
|
|
6
|
+
przy niedostępnym localStorage; opcjonalne zgody wymagają skutecznego zapisu.
|
|
7
|
+
|
|
8
|
+
To mechanizmy wspierające zgodne wdrożenie. Nie są certyfikatem zgodności całej
|
|
9
|
+
witryny ani oceną prawdziwości danych wpisanych przez jej administratora.
|
|
10
|
+
|
|
11
|
+
## WordPress
|
|
12
|
+
|
|
13
|
+
1. W „Banner & texts” wpisz rzeczywistą nazwę administratora, konkretne cele
|
|
14
|
+
opcjonalnego przetwarzania, URL opublikowanej polityki i jej wersję. Zmiana
|
|
15
|
+
celów, odbiorców lub polityki pod zewnętrznym URL wymaga zmiany wersji.
|
|
16
|
+
Zmiana treści lokalnej strony polityki oraz buildu bannera jest wykrywana automatycznie.
|
|
17
|
+
2. Uruchom istniejący skaner. W „Services” sprawdź informacje o wykrytych
|
|
18
|
+
dostawcach: rzeczywisty cel na tej stronie, politykę dostawcy oraz okres
|
|
19
|
+
przechowywania danych lub kryteria jego określenia. Sugestie korzystają
|
|
20
|
+
z tej samej bazy i identyfikatorów co skaner i blokowanie, bez drugiej tabeli
|
|
21
|
+
cookies. Opisy bazy są sugestiami, nie potwierdzeniem konkretnego wdrożenia.
|
|
22
|
+
3. Nierozpoznane lub nieopisane usługi pozostają zablokowane. Zarejestruj
|
|
23
|
+
własną integrację z jej URL-ami i pełnymi informacjami, zamiast zgadywać cel
|
|
24
|
+
nieznanej domeny. Zmiana integracji wymaga nowego identyfikatora usługi.
|
|
25
|
+
4. Link `.open-consent-settings` i shortcode `[cookie_preferences_link]`
|
|
26
|
+
nadal działają. Kontrolka ustawień pozostaje widoczna; przy aktywnych zgodach
|
|
27
|
+
jest też bezpośredni przycisk wycofania wszystkich opcjonalnych zgód.
|
|
28
|
+
5. Zachowaj blokowanie CSP, wyczyść stare cache HTML i sprawdź CDN/reverse proxy.
|
|
29
|
+
HTML zależny od zgód nie może być współdzielony między odwiedzającymi.
|
|
30
|
+
|
|
31
|
+
Samo zaznaczenie kategorii nie zastępuje zgody na odrębnie pokazanego dostawcę.
|
|
32
|
+
Nie należy oznaczać wszystkich „funkcjonalnych” cookies jako ściśle niezbędnych.
|
|
33
|
+
Tabela cookies domyślnie pokazuje także nierozpoznane pozycje.
|
|
34
|
+
|
|
35
|
+
## npm / Next.js
|
|
36
|
+
|
|
37
|
+
Serwer i klient muszą używać tej samej `noticeVersion`. Uaktualniaj ją przy
|
|
38
|
+
zmianach informacji, celów, odbiorców lub polityki. Bez wersji serwerowy helper
|
|
39
|
+
pozostawia opcjonalne domeny zablokowane. Sam import JS nie zastąpi nagłówka HTTP
|
|
40
|
+
CSP i nieaktywnych atrybutów SSR.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
const noticeVersion = '2026-11-06.1';
|
|
44
|
+
const config = {
|
|
45
|
+
mode: 'standalone', lang: 'pl', strictCsp: true, noticeVersion,
|
|
46
|
+
controller: {name: 'RZECZYWISTA NAZWA ADMINISTRATORA'},
|
|
47
|
+
purposes: 'Konkretne cele opcjonalnego przetwarzania na tej stronie.',
|
|
48
|
+
privacyPolicyUrl: '/polityka-prywatnosci',
|
|
49
|
+
services: [{
|
|
50
|
+
id: 'video', name: 'Dostawca filmu',
|
|
51
|
+
description: 'Konkretny cel i zakres integracji, w tym przekazywane dane.',
|
|
52
|
+
privacyUrl: 'https://video.example/privacy',
|
|
53
|
+
retention: 'Rzeczywisty okres lub kryteria usunięcia danych — po weryfikacji.',
|
|
54
|
+
urls: ['https://video.example/'],
|
|
55
|
+
cleanup: {cookies: ['video_session'], localStorage: ['video-id']},
|
|
56
|
+
}],
|
|
57
|
+
};
|
|
58
|
+
// Te dane są wzorem konfiguracji, nie gotową polityką konkretnej witryny.
|
|
59
|
+
const headers = consentCspHeaders({noticeVersion, services: {
|
|
60
|
+
video: {'frame-src': ['https://video.example']},
|
|
61
|
+
}}, request.headers.get('cookie') || '');
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Dla usług z katalogu można ustawić `serviceDisclosures[id]` z polami
|
|
65
|
+
`description`, `privacyUrl`, `retention` i opcjonalnym `cleanup`, bez powielania
|
|
66
|
+
reguł rozpoznawania URL. Dotychczasowe `scripts.analytics` / `scripts.marketing`
|
|
67
|
+
wymagają teraz `service` w każdym skrypcie; wykonanie wymaga zarówno zgody na
|
|
68
|
+
kategorię, jak i daną usługę. API `setServiceConsent` wywołuj w odpowiedzi na
|
|
69
|
+
świadomy wybór użytkownika, a nie podczas automatycznego startu aplikacji.
|
|
70
|
+
|
|
71
|
+
## Zapis decyzji i dowody
|
|
72
|
+
|
|
73
|
+
Przeglądarka zachowuje jeden aktualny rekord: losowy identyfikator decyzji, czas,
|
|
74
|
+
kategorie, wybory dostawców, wersję i kopię pokazanych informacji. `getConsentReceipt()`
|
|
75
|
+
i zdarzenie `cb:consent-receipt` udostępniają go integratorowi. Rekord może służyć
|
|
76
|
+
powiązaniu decyzji z procesami własnego backendu; nie należy wysyłać dodatkowych
|
|
77
|
+
identyfikatorów dostawcom bez potrzeby i odpowiedniej informacji.
|
|
78
|
+
|
|
79
|
+
WordPress zapisuje minimalną kopię decyzji i wersjonowane informacje po stronie
|
|
80
|
+
serwera, z czasem serwera i hashem runtime. Nie zapisuje w tym rekordzie IP,
|
|
81
|
+
user-agenta ani trwałego identyfikatora odwiedzającego. Powtórzenie ID nie zmienia
|
|
82
|
+
istniejącego dowodu. Krótkotrwały, solony skrót adresu służy osobno do ograniczania
|
|
83
|
+
nadużyć endpointu i wygasa po minucie. Zapis nie jest podpisem użytkownika ani
|
|
84
|
+
potwierdzeniem jego tożsamości.
|
|
85
|
+
|
|
86
|
+
- `GET /wp-json/cookie4/v1/consent-receipts?offset=0`: eksport dla administratora,
|
|
87
|
+
100 pozycji na stronę, `nextOffset` wskazuje kolejną partię; wymaga zwykłego
|
|
88
|
+
uwierzytelnienia WordPress REST. Panel Diagnostics eksportuje ostatnie 100.
|
|
89
|
+
- `POST` tego endpointu przyjmuje aktualną wersję i ściśle sprawdzone wybory;
|
|
90
|
+
wymaga nonce. Brak uprawnienia nie daje dostępu do eksportu.
|
|
91
|
+
- Hook `cookie4_consent_recorded` pozwala administratorowi integrować własną
|
|
92
|
+
retencję lub archiwum. `cb:receipt-error` sygnalizuje klientowi błąd wysyłki;
|
|
93
|
+
lokalny pełny rekord pozostaje dostępny dla integratora.
|
|
94
|
+
- Domyślna ważność wyboru i retencja dowodów wynoszą 180 dni. To ustawienie
|
|
95
|
+
produktu, nie uniwersalny termin ustawowy. Backendowy filtr
|
|
96
|
+
`cookie4_receipt_retention_days` pozwala ustalić 1–365 dni. Zasady retencji
|
|
97
|
+
muszą być opisane przez administratora. Usuwanie wykonuje też dzienny WP-Cron;
|
|
98
|
+
przy wyłączonym WP-Cron trzeba zapewnić jego uruchamianie na serwerze.
|
|
99
|
+
|
|
100
|
+
## Wycofanie i ograniczenia techniczne
|
|
101
|
+
|
|
102
|
+
Wycofanie natychmiast zaostrza CSP bieżącego dokumentu przed wywołaniem SDK
|
|
103
|
+
i przeładowaniem, żeby zatrzymać także pingi consent-update i pagehide. Następnie
|
|
104
|
+
aktualizuje decyzję, wyłącza elementy korzystające z subskrypcji,
|
|
105
|
+
wysyła sygnały cofnięcia do używanego mechanizmu GTM/Meta i przeładowuje dokument
|
|
106
|
+
z odmawiającym CSP. Zmiana w innej karcie również odświeża politykę. Stary grant
|
|
107
|
+
serwerowy jest usuwany przed zmianami localStorage, aby inna karta nie odświeżyła
|
|
108
|
+
się ze starym zezwoleniem. Przywrócenie strony z bfcache odświeża ścisłe CSP. Zmiana wersji informacji
|
|
109
|
+
podczas ponownej inicjalizacji nawigacji klientowej również wymusza nowy dokument.
|
|
110
|
+
|
|
111
|
+
Usuwane są tylko jawnie wskazane identyfikatory first-party. WordPress korzysta
|
|
112
|
+
z nazw cookies sklasyfikowanych przez istniejący skaner jako analityczne lub
|
|
113
|
+
marketingowe; należy zweryfikować tę klasyfikację. npm ma `cleanup` per dostawca
|
|
114
|
+
oraz `categoryCleanup`. Nie usuwamy koszyka ani sesji strony „na wszelki wypadek”.
|
|
115
|
+
HttpOnly i dane u dostawcy wymagają odpowiedniej obsługi serwera/dostawcy;
|
|
116
|
+
przeglądarkowy JS nie ma uprawnień do ich dowolnego kasowania. Żądań już
|
|
117
|
+
rozpoczętych przed wycofaniem nie da się cofnąć; aktywność obcego dokumentu iframe
|
|
118
|
+
pozostaje ograniczeniem opisanym poniżej.
|
|
119
|
+
|
|
120
|
+
Polityka CSP kontroluje żądania dokumentu strony, nie całą wewnętrzną aktywność
|
|
121
|
+
zdalnego dokumentu iframe. Zgoda na osadzenie musi uwzględniać przetwarzanie tego
|
|
122
|
+
dostawcy. Lokalne iframe i workery są domyślnie zablokowane, ponieważ ich własne dokumenty
|
|
123
|
+
nie muszą dziedziczyć reguł sieciowych rodzica. Jawnie dopuszczone niezbędne
|
|
124
|
+
workery lub ramki wymagają właściwych nagłówków także na ich odpowiedziach.
|
|
125
|
+
Tracking first-party, proxy, backend, konfiguracja GTM, transfery poza
|
|
126
|
+
EOG, rzeczywiste cele i pełny obowiązek informacyjny wymagają oceny konkretnej
|
|
127
|
+
witryny. Kolory HEX z panelu dostają korektę kontrastu; zaawansowane kolory CSS
|
|
128
|
+
podane w integracji własnej trzeba zweryfikować w jej rzeczywistym otoczeniu.
|
|
129
|
+
|
|
130
|
+
Nie da się rzetelnie zamienić tych testów w gwarancję „100% zgodności każdej
|
|
131
|
+
strony z RODO”. Podstawy: [PKE art. 399–400](https://eli.gov.pl/api/acts/DU/2024/1221/text.html),
|
|
132
|
+
[RODO art. 4, 7, 12–13, 25 i rozdział V](https://eur-lex.europa.eu/legal-content/PL/TXT/?uri=CELEX:32016R0679),
|
|
133
|
+
[raport EROD o bannerach](https://www.edpb.europa.eu/system/files/2023-01/edpb_20230118_report_cookie_banner_taskforce_en.pdf).
|
|
134
|
+
|
|
135
|
+
### Styl przycisków
|
|
136
|
+
|
|
137
|
+
WordPress: **Banner & texts → Consent button style**. Standardowy oznacza
|
|
138
|
+
wypełnioną akceptację i obrysowaną odmowę; ścisły oznacza identyczne przyciski
|
|
139
|
+
decyzji. Zapis preferencji ma neutralny styl. Ustawienie zmienia tylko wygląd,
|
|
140
|
+
nie blokowanie, CSP ani wymagania zgody. Nazwy trybów nie stanowią oceny prawnej.
|
|
141
|
+
W npm domyślną wartością `buttonStyle` jest `standard`. W WordPressie domyślną
|
|
142
|
+
wartością jest `equal`.
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Integracja zgód: npm i WordPress
|
|
2
|
+
|
|
3
|
+
Pakiet i wtyczka korzystają z jednego modelu zgód oraz rejestru rozpoznawania usług. Wyniki skanowania pozostają w istniejącym module `plugin/src/features/scanner` i dotychczasowych opcjach WordPressa. Nie ma drugiej tabeli cookies.
|
|
4
|
+
|
|
5
|
+
[Wymagane informacje i konfiguracja zgód](consent-compliance.md).
|
|
6
|
+
|
|
7
|
+
## Npm: kod własnej strony / Next.js
|
|
8
|
+
|
|
9
|
+
Punkt wejścia: `@app4you/cookie-banner/native`. Sam import i funkcje generujące atrybuty są bezpieczne w SSR. Klient pobiera kod bannera dopiero podczas inicjalizacji. Dotychczasowy bundle IIFE pozostaje w `@app4you/cookie-banner` i `@app4you/cookie-banner/auto`.
|
|
10
|
+
|
|
11
|
+
W komponencie serwerowym można od razu wygenerować nieaktywny iframe:
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { blockedContentProps } from "@app4you/cookie-banner/native";
|
|
15
|
+
|
|
16
|
+
export function Video() {
|
|
17
|
+
return <iframe
|
|
18
|
+
{...blockedContentProps("youtube", "https://www.youtube-nocookie.com/embed/VIDEO_ID")}
|
|
19
|
+
title="Film o naszej firmie"
|
|
20
|
+
width={800}
|
|
21
|
+
height={450}
|
|
22
|
+
allowFullScreen
|
|
23
|
+
/>;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
W HTML nie ma `src`, tylko `data-cb-src`. Brak JS nie uruchomi dostawcy. Identyczne właściwości działają z Reactem i Preactem. Przykład w tym repo faktycznie korzysta z API: `src/demo.tsx`.
|
|
28
|
+
|
|
29
|
+
Inicjalizacja po hydratacji, np. w jednym komponencie klientowym Next.js:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
"use client";
|
|
33
|
+
import { useEffect } from "react";
|
|
34
|
+
import { initializeConsent } from "@app4you/cookie-banner/native";
|
|
35
|
+
|
|
36
|
+
export function ConsentProvider() {
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
let cancelled = false;
|
|
39
|
+
let dispose: (() => void) | undefined;
|
|
40
|
+
initializeConsent({
|
|
41
|
+
mode: "standalone",
|
|
42
|
+
lang: "pl",
|
|
43
|
+
variant: "bar",
|
|
44
|
+
noticeVersion: "2026-11-06.1",
|
|
45
|
+
controller: {name: "RZECZYWISTA NAZWA ADMINISTRATORA"},
|
|
46
|
+
purposes: "Odtwarzanie opcjonalnych filmów przez zewnętrznego dostawcę.",
|
|
47
|
+
privacyPolicyUrl: "/polityka-prywatnosci",
|
|
48
|
+
services: [{
|
|
49
|
+
id: "youtube",
|
|
50
|
+
name: "YouTube",
|
|
51
|
+
description: "Odtwarzanie osadzonych filmów. Po zgodzie Google otrzyma adres IP i dane przeglądarki.",
|
|
52
|
+
privacyUrl: "https://policies.google.com/privacy",
|
|
53
|
+
retention: "Wpisz zweryfikowany okres lub kryteria usunięcia danych dla tego wdrożenia.",
|
|
54
|
+
}],
|
|
55
|
+
}).then(cleanup => {
|
|
56
|
+
if (cancelled) cleanup();
|
|
57
|
+
else dispose = cleanup;
|
|
58
|
+
});
|
|
59
|
+
return () => { cancelled = true; dispose?.(); };
|
|
60
|
+
}, []);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Dla zwykłego skryptu użyj `blockedScriptProps("service-id", "https://provider.example/sdk.js")`. Skrypt inline również musi dostać te atrybuty i `type="text/plain"`. Nie przekazuj aktywnego `src` do `next/script`, preloadu ani frameworkowego komponentu, który sam rozpoczyna połączenie. Identyfikator usługi musi być taki sam w konfiguracji i atrybutach.
|
|
66
|
+
|
|
67
|
+
Dla komponentu wykonującego żądania podczas montowania zastosuj `onServiceConsent` **przed jego zamontowaniem**:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { onServiceConsent } from "@app4you/cookie-banner/native";
|
|
71
|
+
|
|
72
|
+
const unsubscribe = onServiceConsent("support-chat", granted => {
|
|
73
|
+
if (granted) mountChat();
|
|
74
|
+
else unmountChat();
|
|
75
|
+
});
|
|
76
|
+
// Przy odmontowaniu właściciela: unsubscribe().
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`mountChat()` powinno zawierać również import/uruchomienie SDK — nie importuj wcześniej modułu mającego efekty uboczne. Zarejestruj własną usługę w `services` z jej rzeczywistym celem i polityką. `urls` pozwala przypisać dokładne prefiksy URL (porównywane po origin i ścieżce), także własnych skryptów. Domyślnie natywna integracja nie zmienia prototypów przeglądarki; `autoBlock: true` włącza dodatkowy guard dla zewnętrznego, niekontrolowanego kodu.
|
|
80
|
+
|
|
81
|
+
Dostępne są też `hasServiceConsent(id)` i `setServiceConsent(id, boolean)`. Wycofanie zgody przeładowuje dokument, ponieważ usunięcie znacznika script nie usuwa uruchomionych timerów i listenerów SDK. Zgody usług są niezależne od kategorii analityka/marketing.
|
|
82
|
+
|
|
83
|
+
## WordPress
|
|
84
|
+
|
|
85
|
+
Warstwy działania:
|
|
86
|
+
|
|
87
|
+
1. `script_loader_tag`, `wp_inline_script_attributes`, `render_block`, `embed_oembed_html` przekształcają rozpoznane zasoby i kod powiązany z enqueue.
|
|
88
|
+
2. Bufor całej odpowiedzi PHP obejmuje również surowe `echo`, iframe i rozpoznane inline loadery. Parser WP neutralizuje `src`, alternatywne adresy lazy load, srcset i odpowiednie wskazówki połączeń. Skrypty są `text/plain`.
|
|
89
|
+
3. Synchronous bootstrap jest przenoszony na początek gotowego head, przed kod wydrukowany przed `wp_head`. Ma atrybuty wyłączenia optymalizacji dla popularnych loaderów.
|
|
90
|
+
4. Guard przechwytuje natywne właściwości URL, `setAttribute`, wstawianie węzłów i typowe operacje HTML przed wywołaniem implementacji przeglądarki. Dodatkowo zatrzymuje rozpoznane opcjonalne żądania `fetch`, XHR i `sendBeacon`. Nieznane iframe są grupowane osobno według dostawcy/domeny i pozostają nieaktywne do uzupełnienia informacji; celu nieznanych skryptów nie zgadujemy.
|
|
91
|
+
5. Runtime pokazuje lokalny boks bez zewnętrznej miniatury, aktywuje wyłącznie wybraną usługę i zachowuje kolejność odblokowywanych skryptów. Piksele śledzące i wskazówki połączeń nie dostają dużych widocznych boksów.
|
|
92
|
+
6. Istniejący skaner rozróżnia zablokowany element od requestu zaobserwowanego w Performance API. Audyt administratora wymusza odmowę bez nadpisywania jego zapamiętanych wyborów.
|
|
93
|
+
|
|
94
|
+
Własny kod WordPressa może emitować:
|
|
95
|
+
|
|
96
|
+
```html
|
|
97
|
+
<iframe hidden data-cb-service="youtube"
|
|
98
|
+
data-cb-src="https://www.youtube.com/embed/VIDEO_ID" title="Film"></iframe>
|
|
99
|
+
<script type="text/plain" data-cb-service="custom-analytics"
|
|
100
|
+
data-cb-src="https://metrics.example/sdk.js"></script>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Filtr `cookie4_config` pozwala dodać `services` (ten sam format co npm) i ustawić `autoBlock: false` w razie konfliktu konkretnej witryny. To wyłącza dodatkowy guard; transformacja PHP pozostaje. Własne usługi oznaczone w HTML pozostają blokowane bez zgody niezależnie od obecności w bazie.
|
|
104
|
+
|
|
105
|
+
Boksy dziedziczą rodzinę fontów i kolor tekstu strony, z kompaktowymi rozmiarami tekstu i przycisków. Tło oraz obramowanie są delikatnymi odcieniami bieżącego koloru, a YouTube ma lokalną ikonę odtwarzania bez pobierania miniatury. Strona może nadpisać zmienne CSS: `--cb-content-background`, `--cb-content-color`, `--cb-content-border`, `--cb-content-radius`, `--cb-content-primary`, `--cb-content-button-text` oraz klasę `.cb-content-placeholder`.
|
|
106
|
+
|
|
107
|
+
## Bazy i aktualizacje
|
|
108
|
+
|
|
109
|
+
- `plugin/includes/cookie-database.json`: istniejąca Open Cookie Database, zaktualizowana w miejscu — 2280 wpisów.
|
|
110
|
+
- `plugin/includes/service-database.json`: dane Third Party Web — 2141 dostawców, 3132 wzorce domen.
|
|
111
|
+
- `tracker-database.json`: niewielka warstwa dokładniejszych reguł produktów i metadanych (np. odróżnienie GA od kontenera GTM).
|
|
112
|
+
- `database-sources.json`: wersje źródłowe; `bun run update:databases` odtwarza import. Aktualizacja rewizji jest świadomą zmianą kodu, bez pobierania bazy podczas wizyty użytkownika. Import nie wykonuje pobranego JS.
|
|
113
|
+
- Licencje i atrybucja są w `plugin/NOTICE` oraz `plugin/licenses/`.
|
|
114
|
+
|
|
115
|
+
Preferencje pokazują usługi skonfigurowane lub zaobserwowane na witrynie, a nie całą bazę. Trzeba zweryfikować rzeczywisty cel przetwarzania, administratorów i polityki nieznanych usług. Kategorie z bazy są wskazówką, a nie oceną prawną konkretnej konfiguracji.
|
|
116
|
+
|
|
117
|
+
## Ograniczenia integracji
|
|
118
|
+
|
|
119
|
+
Nie deklarujemy automatycznej pełnej zgodności całej witryny z RODO. Baza nie zna wszystkich celów; guard nie stanowi kompletnego firewalla przeglądarki. Nie obejmuje każdej ścieżki, np. Workerów, obcych realmów, wcześniej przechwyconych API, dowolnego `document.write`, zasobów CSS, Early Hints i serwerowego trackingu. Nie usuwa cudzych cookies HttpOnly ani cookies na domenie dostawcy. Te przypadki wymagają integracji u źródła i audytu docelowej strony.
|
|
120
|
+
|
|
121
|
+
`testMode` i `autoAcceptAll` nie udzielają już zgód. Dotychczasowe zgody bez aktualnego rekordu wersji są uznawane za nieważne; nowy zapis ma wersję, czas i okres ważności 180 dni (wybór produktu, nie uniwersalny termin ustawowy). Google działa w Basic Consent Mode: GTM wymaga aktywnej zgody na usługę oraz cel, a przy odmowie nie jest ładowany. Tagi wewnątrz kontenera muszą nadal mieć poprawnie skonfigurowane wymagania zgód.
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
## Strict network CSP (server integration)
|
|
125
|
+
|
|
126
|
+
`@app4you/cookie-banner/native` exports server-safe `consentCspHeaders`,
|
|
127
|
+
`buildConsentCsp` and `readCspConsent`. This is an HTTP policy, not a policy
|
|
128
|
+
installed by a client effect. Apply it to the initial HTML response:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import { consentCspHeaders } from '@app4you/cookie-banner/native';
|
|
132
|
+
|
|
133
|
+
const csp = {
|
|
134
|
+
noticeVersion: "2026-11-06.1", // Same value in the client config.
|
|
135
|
+
services: {
|
|
136
|
+
youtube: {
|
|
137
|
+
'script-src': ['https://www.youtube.com', 'https://s.ytimg.com'],
|
|
138
|
+
'frame-src': ['https://www.youtube.com', 'https://www.youtube-nocookie.com'],
|
|
139
|
+
},
|
|
140
|
+
analytics: {
|
|
141
|
+
'script-src': ['https://analytics.example.com'],
|
|
142
|
+
'connect-src': ['https://analytics.example.com'],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
const headers = consentCspHeaders(csp, request.headers.get('cookie') || '');
|
|
147
|
+
// Set every returned header on the HTML response. Preserve other Vary tokens.
|
|
148
|
+
// Initialize the client banner with strictCsp: true and the same service IDs.
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
For Next.js, compute these headers in middleware/proxy for document routes;
|
|
152
|
+
make the protected route/layout dynamic (`export const dynamic = 'force-dynamic'`)
|
|
153
|
+
and bypass CDN/full-page caching. Remove external HTTP Link/103 Early Hints and
|
|
154
|
+
HTML preconnect/prefetch hints; the helper disables DNS prefetch but cannot rewrite
|
|
155
|
+
HTML or a proxy configuration. A static export cannot emit a different HTTP
|
|
156
|
+
policy per visitor. Keep `blockedContentProps` / `blockedScriptProps` on optional
|
|
157
|
+
resources, including server-rendered markup. `initializeConsent` belongs in a
|
|
158
|
+
client effect; constructing response headers belongs on the server. The included
|
|
159
|
+
|
|
160
|
+
The cookie `cb_csp_consent` contains only explicitly granted service IDs, expires
|
|
161
|
+
in 180 days, and uses Path=/, SameSite=Lax and Secure on HTTPS. The server ignores
|
|
162
|
+
unknown IDs; the cookie cannot add arbitrary origins. Every consent change reloads
|
|
163
|
+
the document before the client dispatches integration activation. Cross-tab storage
|
|
164
|
+
changes reload strict-CSP documents too. Serve one consent scope per host/path-root;
|
|
165
|
+
applications sharing an origin must use a common service registry.
|
|
166
|
+
|
|
167
|
+
Default policy: `default-src 'none'`, self-hosted resources, inline scripts/styles,
|
|
168
|
+
data images/fonts; no external sources, objects or external form submissions.
|
|
169
|
+
Service allowlists accept HTTPS origins only, optionally with a leading wildcard.
|
|
170
|
+
`essential` allows explicitly reviewed necessary destinations. `allowEval: true`
|
|
171
|
+
is an explicit optimizer compatibility escape hatch, not enabled by default.
|
|
172
|
+
Inline scripts remain allowed for framework/WordPress compatibility: this is a
|
|
173
|
+
network privacy policy, not a nonce-based XSS protection policy.
|
|
174
|
+
|
|
175
|
+
## WordPress CSP and caches
|
|
176
|
+
|
|
177
|
+
Strict CSP is enabled by default on frontend HTML, both as a response header and
|
|
178
|
+
as the first head meta policy (the header enforces additional directives such as
|
|
179
|
+
frame-ancestors). Registered service domains reuse the existing scanner registry;
|
|
180
|
+
unknown destinations stay blocked. Unknown HTTPS iframe origins are registered
|
|
181
|
+
for frame-src only from the actual HTML of the current response; consent cookies
|
|
182
|
+
cannot invent a destination. Customize `cookie4_csp_services` with a map of
|
|
183
|
+
service IDs to directive/origin arrays; use `cookie4_csp_essential` for necessary
|
|
184
|
+
origins. `cookie4_strict_csp` controls the whole mode. `cookie4_csp_allow_eval` can
|
|
185
|
+
force-disable the eval compatibility required by WP Rocket Delay JS, at the cost
|
|
186
|
+
of disabling that loader's behavior. Eval is otherwise allowed only while that
|
|
187
|
+
active optimizer has Delay JS enabled. LiteSpeed Delay JS instead needs local
|
|
188
|
+
`blob:` scripts; `cookie4_csp_allow_blob_scripts` can override that compatibility
|
|
189
|
+
exception. Neither exception adds an external network destination.
|
|
190
|
+
|
|
191
|
+
The plugin sets private/no-store HTML, Vary: Cookie, DONOTCACHEPAGE and LiteSpeed
|
|
192
|
+
no-cache controls, prevents LiteSpeed page-cache storage and WP Rocket HTML cache writes.
|
|
193
|
+
It purges both optimizers on deployment/activation and regenerates Rocket config
|
|
194
|
+
and Apache rules. Rocket's DONOTCACHEPAGE override is installed only when this
|
|
195
|
+
plugin defined that constant itself; cache writes remain disabled independently.
|
|
196
|
+
Local JS/CSS minification, combining and delay remain testable and active.
|
|
197
|
+
External HTML resource hints are removed, HTTP Link hints removed, and DNS prefetch
|
|
198
|
+
is disabled. Assets themselves remain cacheable.
|
|
199
|
+
|
|
200
|
+
Deploy through plugin activation/admin or explicitly run
|
|
201
|
+
`wp eval 'cookie4_csp_refresh_cache();'` **before reopening public traffic**. An
|
|
202
|
+
already cached HTML response can be served before WordPress loads the updated
|
|
203
|
+
plugin. Purge and bypass HTML at any additional CDN/reverse proxy/server cache;
|
|
204
|
+
PHP cannot reconfigure an unidentified upstream system or remove 103 Early Hints
|
|
205
|
+
it emits. Do not cache granted HTML variants, and do not let a CDN override no-store.
|
|
206
|
+
The meta policy is defense in depth, not permission to ignore these requirements.
|
|
207
|
+
|
|
208
|
+
CSP does not stop first-party tracking/proxy endpoints, server-to-server requests,
|
|
209
|
+
ordinary user navigation, or control requests inside an allowed cross-origin
|
|
210
|
+
iframe. YouTube's nested third-party dependencies become possible after YouTube
|
|
211
|
+
consent. Review the chosen integration's whole purpose and vendor dependencies.
|
|
212
|
+
This implementation does not itself establish legal compliance for a website.
|
|
213
|
+
|
|
214
|
+
References: [MDN CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP),
|
|
215
|
+
[WP Rocket caching](https://docs.wp-rocket.me/article/1528-page-caching).
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
## WordPress administrator workspace
|
|
219
|
+
|
|
220
|
+
The WordPress panel now has Overview, Banner & texts, Services, Cookies & scan,
|
|
221
|
+
WordPress integration and Diagnostics sections. Banner and service drafts remain
|
|
222
|
+
mounted when switching sections; the banner save indicator preserves edits made
|
|
223
|
+
while an earlier save is in flight.
|
|
224
|
+
|
|
225
|
+
Services can be registered through the panel with an ID, name, purpose, HTTPS URL
|
|
226
|
+
prefixes and optional privacy policy URL. The same saved definitions feed scanner
|
|
227
|
+
detection, HTML blocking, frontend service preferences and CSP. Built-in IDs cannot
|
|
228
|
+
be overridden. To change an integration's purpose/destinations, create a new ID:
|
|
229
|
+
the server retains a hash of prior definitions so deleting/recreating a service
|
|
230
|
+
cannot reuse earlier consent for something different.
|
|
231
|
+
|
|
232
|
+
Diagnostics exposes local prerequisites, detected cache adapters and known other
|
|
233
|
+
active consent plugins. Its explicit homepage check fetches HTML without executing
|
|
234
|
+
it and reports actual response headers for the administrator session; this does
|
|
235
|
+
not replace anonymous full-site request testing. Native WordPress Site Health also
|
|
236
|
+
shows these prerequisites and support information.
|
|
237
|
+
|
|
238
|
+
The live banner preview uses a sandbox that cannot read/write the site's actual
|
|
239
|
+
consent storage. It loads locally bundled assets; preview choices and changing
|
|
240
|
+
appearance do not reset a real visitor's consent.
|
|
241
|
+
|
|
242
|
+
### Te same funkcje poza WordPressem
|
|
243
|
+
|
|
244
|
+
Rdzeń npm i wtyczka używają tych samych komponentów i mechanizmów zgody.
|
|
245
|
+
W npm domyślny `buttonStyle: 'standard'` daje wypełnioną akceptację i obrysowaną
|
|
246
|
+
odmowę. WordPress domyślnie wybiera `'equal'`, czyli jednakowy wygląd obu
|
|
247
|
+
przycisków. Ustawienie dotyczy wyglądu przycisków.
|
|
248
|
+
|
|
249
|
+
W konfiguracji npm dostępne są również `localizations`, `customTexts`,
|
|
250
|
+
`serviceDisclosures`, `categoryCleanup`, `autoBlock: true`, `strictCsp: true`,
|
|
251
|
+
`receiptEndpoint` i `receiptNonce`. CSP wymaga nagłówka z serwera aplikacji;
|
|
252
|
+
przykład Next.js/SSR znajduje się w `docs/multilingual.md`.
|
|
253
|
+
|
|
254
|
+
Z `@app4you/cookie-banner/native` można odczytać `getDetectedServices()` (zaobserwowane
|
|
255
|
+
usługi z tego samego rejestru), `getConsentReceipt()` i korzystać z
|
|
256
|
+
`hasServiceConsent`, `setServiceConsent`, `onServiceConsent` oraz nieaktywnych
|
|
257
|
+
atrybutów `blockedContentProps` / `blockedScriptProps`.
|
|
258
|
+
|
|
259
|
+
Panel, zapis w tabeli bazy danych WordPressa, WPML/Polylang i czyszczenie cache
|
|
260
|
+
wtyczek są adapterami WordPressa. W innej aplikacji jej backend odbiera dowody przez
|
|
261
|
+
`receiptEndpoint`, a ustawienia przekazuje się jako konfigurację npm. Sam pakiet
|
|
262
|
+
przeglądarkowy nie tworzy bazy danych ani panelu administracyjnego hosta.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Bezpieczny deployment i limity dowodów zgody
|
|
2
|
+
|
|
3
|
+
## Przesyłanie do WordPressa
|
|
4
|
+
|
|
5
|
+
Usunięto grunt-ftp-push i transport FTP. `grunt deploy` i `grunt dev:ssh` korzystają z rsync przez SSH; `grunt dev:ftp` jest wyłącznie aliasem do bezpiecznej ścieżki. Nie ma powrotu do zwykłego FTP. Wymagane są rsync, OpenSSH, klucz lub agent SSH i wcześniej zweryfikowany klucz serwera w known_hosts.
|
|
6
|
+
|
|
7
|
+
```dotenv
|
|
8
|
+
SSH_HOST=example.com
|
|
9
|
+
SSH_USER=deploy
|
|
10
|
+
SSH_PORT=22
|
|
11
|
+
SSH_WP_PLUGINS_FOLDER_PATH=/var/www/wp-content/plugins
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Ścieżka musi być bezwzględna, bez spacji i metaznaków powłoki. Stare FTP_HOST/FTP_USERNAME/FTP_PASSWORD nie uruchomią transmisji. BatchMode i StrictHostKeyChecking=yes powodują zatrzymanie przy braku uwierzytelnienia lub nieznanym/zmienionym kluczu. Potwierdź fingerprint niezależnym kanałem przed dodaniem klucza — samo pobranie przez ssh-keyscan nie jest weryfikacją.
|
|
15
|
+
|
|
16
|
+
## WordPress.org SVN
|
|
17
|
+
|
|
18
|
+
SVN_USERNAME i SVN_PASSWORD nadal działają. SVN 1.10+ odczytuje hasło przez --password-from-stdin, hasło nie trafia do argv ani konfiguracji Grunta i jest usuwane ze środowiska procesu potomnego svn. Polecenia uwierzytelniane nie przechodzą przez sh -c. Weryfikacja certyfikatu pozostaje włączona, cache hasła jest wyłączony. Hasło zawierające CR/LF jest odrzucane — stdin wymaga pojedynczej linii.
|
|
19
|
+
|
|
20
|
+
## Publiczne dowody zgody
|
|
21
|
+
|
|
22
|
+
Kategorie muszą zawierać dokładnie essential=true, analytics=boolean i marketing=boolean. Inne pola kategorii, zagnieżdżone payloady i skalary są odrzucane. Limit body: 16 000 bajtów; pełny zapis z informacjami administratora: 16 384 bajty. Długie konfiguracje przekraczające ten limit zwracają 413 i wymagają skrócenia informacji.
|
|
23
|
+
|
|
24
|
+
Atomowe limity: 600 poprawnych żądań na minutę globalnie i 120 na minutę dla jednego z 256 stałych koszyków adresów. Koszyki mogą współdzielić limit; nie przechowują surowych adresów. Spóźnione żądanie nie może cofnąć okna czasu. Liczba liczników wynosi najwyżej 258 (capacity, minute, ip_0…ip_255).
|
|
25
|
+
|
|
26
|
+
Domyślny budżet to 10 000 dowodów, zmieniany filtrem cookie4_receipt_max_records (zakres 1–100 000). Przy wyczerpaniu nowe dowody zwracają 503, a już zapisany identyfikator pozostaje idempotentny. W tym momencie wykonywane jest także usuwanie przeterminowanych dowodów, niezależnie od WP-Cron. Retencja nadal korzysta z cookie4_receipt_retention_days (domyślnie 180 dni). Frontend nadal emituje cb:receipt-error przy nieudanym zapisie serwerowym; należy monitorować ten sygnał i pojemność na witrynach o większym ruchu. Odmowa i cofnięcie zgody nie zależą od dostępności archiwum.
|
|
27
|
+
|
|
28
|
+
Rezerwacja budżetu i zapis są jedną transakcją. Przerwanie procesu lub rollback nie zużywa miejsca. Usuwanie i zwalnianie budżetu również jest transakcyjne. Migracja przygotowuje licznik przed uruchomieniem nowej retencji; na MySQL wymaga InnoDB i w razie potrzeby konwertuje te dwie tabele. Przy błędzie migracji zapis jest odrzucany. Dotychczasowe dowody nie są przycinane ani usuwane z powodu samej migracji. Stare transients z poprzedniej wersji mogą pozostać do standardowego sprzątania WordPressa.
|