Internals — Build custom (packages/cmp-web/builds/)
Non è API pubblica. Un "build custom" è un bundle separato che consuma
@avacy/cmp-webcome libreria e aggiunge un layer specifico per un cliente/scenario — non è raggiungibile da un integratore generico, è materiale per il team.
web — bundle di riferimento
Il build "vanilla": entrypoint minimo, nessun layer aggiuntivo. È il bundle che carica un sito normale via CDN — tutto quello che fa è l'auto-init standard descritto in Lifecycle. Serve da baseline: ogni altro build parte da qui e aggiunge comportamento sopra.
cmp-saas-preview — anteprima nell'editor SaaS
Due file, entrambi già coperti in dettaglio in Internals — cmp-web § Ambiente di esecuzione:
neutralize-iframe.tsimpostawindow.__AVACY_FORCE_STANDARD_LAYOUT__— mostra il layout standard (non compatto) anche se il bundle gira dentro l'iframe di anteprima dell'editor.- La build è anche marcata a livello di costante di compilazione (
__AVACY_IS_PREVIEW__, letta daisPreviewBuild()) — non un flagwindow, apposta perché protegge l'archiviazione di consensi reali: un click "Accetta" nell'editor non deve scrivere un consenso vero nell'archivio del cliente che si sta configurando.
rai — il build più grande e complesso
Tre layer aggiuntivi sopra il core, indipendenti fra loro: v2-compat (retrocompatibilità con l'API del vecchio banner), rai-native (bridge con l'app nativa iOS/Android), syndication (consenso ereditato da un CMP master upstream).
Boot e merge della config
entry.ts non usa l'auto-init standard di cmp-web: importa defineCustomElements esplicitamente e chiama init() da sé, dopo aver registrato i provider custom. Ordine deliberato:
v2-compatimportato per primo, prima ancora del modulo Stencil pesante — un modulo TypeScript leggero valuta più in fretta del componente Stencil, e il compat deve installarsi prima diDOMContentLoadedper vincere la race con l'evento di boot nativo (oil-dom-loaded) e non lasciare una finestra in cui script partner cercanowindow.AS_OILe non lo trovano ancora.- Registrazione provider (
registerStoreProvider('syndication', ...),registerStoreProvider('rai-native-webview', ...)), bridge nativo e deep-link legacy — devono essere pronti prima cheinit()risolvastore.type. defineCustomElements(), poi merge config, poiinit(merged).
Merge della config: RAI_CONFIG (bake-in, config.json) come base, l'inline #avacy-config sopra — ma non un semplice spread flat. core e store sono deep-merge a un livello (un inline { store: { type: 'rai-native-webview' } } non cancella il consentKey bakeato). frameworks fa merge per discriminatore (tcf/acm/custom/gcm): un inline può sovrascrivere solo una chiave annidata (es. tcf.gvlUrl per ambiente) senza dover riscrivere l'intero array e perdere i vendor custom bakeati. Tutte le altre chiavi restano last-write-wins.
consentFilter RAI-specifico: applica una regola di legittimo interesse sensibile allo stato per le azioni bulk (Accetta/Rifiuta tutto), diversa da quella generica del core — LI "standard" (TCF, e custom senza opt-out) preservato da entrambe le bulk action; LI "opt-out" (custom purposes con optOut: true) preservato da Deactivate ma forzato ON da Activate (ri-attiva un opt-out che l'utente aveva tolto). Un RejectAll coalizzato da un Personalized (obiezione esplicita dalla CPC) passa attraverso senza alterazioni — l'utente ha già spento tutto consapevolmente.
rai-native — bridge con l'app nativa
Il bridge notifica la shell nativa (Android via metodi diretti su window.Android, iOS via postMessage sui message handler webkit) di 3 eventi: consenso decodificato (sendDecodedConsent), mostra WebView (show/showView), distruggi WebView (destroy/hideView). Fault-tolerant: se né window.Android né il message handler webkit esistono (bundle caricato fuori da una WebView RAI), ogni chiamata è un no-op silenzioso — consuma solo la superficie pubblica di cmp-web (CoreEvents, getContextData, eventi DOM Tier 1), zero accesso allo store interno Stencil.
Lo store nativo (RaiNativeWebViewStoreProvider) persiste in un formato che rispecchia il contratto legacy RAI, non un formato Avacy nativo: blob principale sotto una chiave maiuscola + <CHIAVE>_EXPIRY, TCF proiettato nelle variabili IABTCF_* standard, ACM mergiato in IABTCF_AddtlConsent, custom proiettato in customVendors/customPurposes, GCM proiettato solo se esiste storage GCM standalone esplicito (in modalità mapping resta un no-op intenzionale).
Due deep-link legacy letti dalla querystring (?prefcenter=1 apre la CPC, ?avacy-rejectall=1 persiste un RejectAll) — cachati dopo la prima lettura, condivisi fra il bridge (seed di cpcOpen al boot) e l'handler post-avacy:ready.
syndication — consenso ereditato da un master upstream
Attivazione automatica: se window.AVACY_SYNDICATION_TCSTRING (canonico) o il legacy AS_OIL_SYNDICATION è presente PRIMA che il bundle carichi, entry.ts forza store.type: 'syndication' sopra qualunque config — vince sempre sullo store configurato, perché il master ha già deciso il consenso e uno store locale divergerebbe. Se sono definiti entrambi i globali, vince il canonico e viene loggato un warning.
Il provider è in-memory per design — writeConsent è un no-op, non persiste mai nulla: il consenso del child segue sempre quello del master, non ha una copia propria da salvare.
⚠️ Re-stamping "bit-surgical", non decode/encode completo. Per sovrascrivere i 3 campi che il child deve cambiare (IAB TCF v2.2 §B.1) il provider non passa dalla libreria
@iabtechlabtcf/core(costerebbe ~50KB in più nel bundle) — modifica direttamente i bit nel segmento core della TCString, un percorso da ~1KB senza dipendenze runtime. Chi tocca questo codice deve capire l'encoding binario della TCString, non solo l'API della libreria IAB.
v2-compat — retrocompatibilità con window.AS_OIL/window.AVACY
Reimplementa la superficie pubblica del banner legacy (v2.43.x, oil.js) sopra la v3: ogni metodo del vecchio AS_OIL/AVACY è mappato sulla nuova API Tier 1. Organizzato per gruppo (consent-actions, ui-control, consent-query, cookie-config-debug, event-collection, misc) — 6 moduli sotto methods/, caricato come side-effect import così il bundle cmpweb-rai.esm.js porta il compat insieme al core v3.
Non tutto è mappato di proposito: applyGDPR, clearVendorlistCaches, getLegalText, getLoginStatus, setLoginStatus, status, getFullConfiguration sono esplicitamente fuori scope — RAI non li chiama mai in produzione (verificato contro l'uso reale, non solo l'API storica). Un sito che dipendesse da uno di questi vedrebbe il metodo assente, non un adattamento silenzioso.