Changelog
Changelog
What changed in pik.li, most recent first.
-
(notte) — Testi legali riscritti, IP completo, generazione in blocco, nuovi utenti
- Testi legali riscritti da capo (termini, privacy, cookie, policy per le autorità): l'italiano in registro giuridico e in terza persona («il Cliente», «InCloud»), poi le altre otto lingue scritte dall'italiano da giuristi madrelingua e riviste ciascuna da un revisore madrelingua diverso — nessun traduttore automatico. Fornitori dei server reali, moderazione con l'IA su server di InCloud in Italia, log e backup a 30 giorni.
-
IP completo di chi apre un link (docs/34 §3, docs/60 §15): conservato per intero quanto il dato del clic, visibile per intero solo allo staff e nell'export per le autorità, al titolare del link sempre mascherato (
151.78.52.•••) nel registro, negli export e nelle API. -
Generazione in blocco (docs/64), nei piani a pagamento: una destinazione, quanti link servono, e via — riquadro con i link da copiare, CSV da scaricare e da riscaricare, anche via API (
POST /api/v1/links/generate). Un lotto verso la stessa destinazione è valutato dall'IA una volta sola, non link per link. - Nuovo utente dall'amministrazione, anche admin (docs/22 §7): invito per e-mail nella sua lingua o password impostata dallo staff; il ruolo admin lo assegna solo il superadmin; al primo accesso i termini.
- Log dell'applicazione e di nginx in file propri ruotati a 30 giorni, backup del database di pik.li a 30 giorni; niente più «da confermare» né «bozza» nelle pagine.
- Barra in alto delle pagine pubbliche che non sborda più su telefono; il listino non promette più la carta come metodo a sé; date inglesi all'inglese.
-
(sera) — Produzione, supporto, ordini, termini nuovi, cripto
-
pik.li è in produzione su hosting.incloud.srl (docs/14): servizio web e servizio dei job (che è anche lo scheduler dei lavori ricorrenti), database e Redis su charizard-sql in rete privata, certificato Let's Encrypt, i domini dei link letti dal database e passati a nginx ogni minuto.
www.pik.liporta apik.li. L'host del sito non viene più scambiato per un dominio dei link. - Supporto con i ticket (docs/61): modulo, ticket aperti e chiusi in due sezioni richiudibili, al massimo tre aperti insieme, conversazione come una chat che si aggiorna da sola. Stati Aperto, In lavorazione, Chiuso, Risolto; il cliente segna «risolto», lo staff chiude. Senza risposta del cliente per 48 ore il ticket si chiude da solo, con e-mail e WhatsApp. Immagini da 25 a 350 KB, decodificate per intero e ricodificate senza metadati: un file che non sembra un'immagine non entra. In amministrazione la voce «Ticket» con il numero delle richieste che aspettano noi.
- Ordini e rimborsi (docs/57): pagina «Ordini» nell'area cliente, stati del dominio leggibili (registrato, zona DNS da creare, in attesa collaudo DNS, pronto…), «Verifica stato» ogni cinque minuti e un controllo automatico ogni tre. Il dominio si registra anche se la zona Cloudflare non nasce subito, e la zona si riprova dopo. Se un dominio pagato non si può registrare, il cliente chiede il rimborso da un modulo e lo staff lo restituisce con PayPal o lo rifiuta con un motivo. Sparito il «Paga» su un ordine già pagato.
- Chiudere l'account (docs/59): la richiesta mette l'account in attesa di cancellazione per sei mesi — accesso e link spenti, dati intatti — e poi lo cancella davvero; i documenti fiscali restano dieci anni. L'amministrazione può fermare la cancellazione, spostarne la data, correggere i dati, ed esportare tutto un account per le autorità (ZIP con impronte, motivo obbligatorio, nel registro).
- Termini, privacy e policy per le forze dell'ordine riscritti in nove lingue (docs/27 §9, domande aperte in docs/60): la responsabilità dei link è del cliente, i link portano solo dove sceglie il cliente, il sito può ospitare pubblicità, i dati alle autorità su richiesta valida. Nel footer il collegamento alla policy e l'indirizzo [email protected]. Versione dei testi 2026-09-24.
- Importa/Esporta si spiega da solo (docs/62): una guida a tendine con le colonne, un file d'esempio da scaricare, i limiti del proprio piano. L'import legge i CSV di Excel (punto e virgola, tabulazioni, codifiche Windows) invece di sbagliare in silenzio, e dice quante righe ha scartato e perché.
- Documentazione API completa in nove lingue su /help (docs/58), ogni endpoint con esempi reali; ogni errore dell'API porta il link alla sua spiegazione.
- Menu: le sezioni si chiamano per quello che contengono (Domini e DNS, Strumenti, Piano e pagamenti) al posto di «Crescita»; «Stato dei servizi» e «Supporto» nel menu del profilo; una sola voce accesa per pagina (su «Compra un dominio» non si accendeva più anche «Domini»).
- Criptovalute con NOWPayments: Bitcoin, Ethereum, Monero, USDT e USDC. La firma delle notifiche si controlla come la calcola NOWPayments (la verifica di prima avrebbe rifiutato ogni pagamento vero), e una notifica attiva solo il pagamento della fattura che abbiamo aperto noi, per l'importo giusto.
- Pagamento in criptovalute sulla nostra pagina (docs/49): il cliente sceglie la moneta al checkout (Bitcoin da 20 €, le altre dal minimo di NOWPayments), paga a un indirizzo con importo e QR, e la pagina chiede lo stato solo al nostro server. Un lavoro ogni minuto controlla i pagamenti aperti: il piano si attiva e il dominio si registra anche se la pagina è stata chiusa. Il pagamento vale quando i fondi sono arrivati («finished»); i pagamenti in attesa si riaprono dalla pagina Ordini. Anche i domini si comprano in cripto. Stripe non compare più al cliente.
- Tetto di redirect al giorno (docs/63): 1.000 per i link anonimi e per il piano Base, 30.000 per Premium, illimitati per Business, tutti modificabili dall'amministrazione anche per il singolo utente. Oltre il tetto il link mostra una pagina che dice quando si riapre (a mezzanotte, ora italiana); il proprietario è avvisato all'80% e al 100% e vede il consumo di oggi nel menu.
- Ogni pagina ha il suo titolo nella scheda del browser («Ordini — pik.li», «Utenti — pik.li admin»), nella lingua di chi la legge.
- Mai più «Content missing»: un link dentro un riquadro che porta a un'altra pagina apre la pagina intera (coda di moderazione, impostazioni della privacy, e per sicurezza ovunque).
-
Dati societari nelle pagine legali con
IT04209270364e il paese nell'indirizzo; fornitori dei server elencati nell'informativa privacy. - Indirizzo del supporto: [email protected] in ogni lingua.
-
pik.li è in produzione su hosting.incloud.srl (docs/14): servizio web e servizio dei job (che è anche lo scheduler dei lavori ricorrenti), database e Redis su charizard-sql in rete privata, certificato Let's Encrypt, i domini dei link letti dal database e passati a nginx ogni minuto.
-
Verifica in due passaggi, impersonificazione, PayPal live, zone DNS
- Verifica in due passaggi con Google Authenticator o qualunque app TOTP (docs/54): si attiva e si disattiva solo con un codice dell'app, dieci codici di recupero mostrati una volta, il login si ferma dopo la password finché non arriva il codice. Chiuse due scorciatoie che lo saltavano: la registrazione rapida con un account esistente e il link di conferma dell'e-mail.
- Scheda utente in amministrazione: azzerare il 2FA, impostare una nuova password (chiude le sessioni), modificare nome, e-mail e dati di fatturazione, tutto nel registro con prima/dopo.
- Impersonificazione come in RIC (docs/56): voce «Impersonation» nel menu, ricerca dell'utente, motivo obbligatorio, e una pastiglia rossa in alto su ogni pagina per tornare alla propria sessione.
- PayPal sandbox o live con un interruttore in Dati Staging (docs/53), chiavi live salvate e consultabili dietro l'occhio, catalogo di prodotti e piani creato in entrambi gli ambienti (docs/51). Dati Staging esiste anche in produzione.
- Il rilascio non cambia più i dati: account, password, piani, domini e chiavi si creano solo se mancano.
- Zone DNS di tutti i domini in un pannello solo, e le prove all'IA si accodano e si aggiornano da sole (docs/52).
-
Fatture col modello inCloud (docs/55): stesso impaginato della carta di inCloud, numerazione
22/2026, modalità di pagamento vera (PayPal con l'ID della transazione, carta, cripto con importo e cambio), scadenza «pagata». Si correggono dall'amministrazione — numero, data, cliente, righe — e la correzione è quella che scarica anche il cliente. Export per il commercialista: XLSX del registro, XML FatturaPA validato sullo XSD ufficiale 1.2.3, ZIP con registro, PDF e XML del periodo.
-
(notte) — La promessa, il listino onesto, il modulo corto
- La promessa di fiducia in home (docs/47), sotto il box di accorciamento e in forma ridotta sull'anteprima del link e sulla faccia di lnkz.li: «Il link va dove dici tu. Punto.», tre negazioni concrete — niente indirizzi nascosti nel QR, niente malware dietro il link corto, niente pubblicità tra il click e la pagina — e il bottone «Prova per credere» che porta al campo. Nove lingue scritte come messaggio in quella lingua, non tradotte.
- Il listino non spunta più quello che non c'è. Targeting, team, SSO e DPA sono nel catalogo dei piani ma non consegnati: ora dicono «in arrivo» nelle card e nella tabella di confronto, come già faceva l'area abbonamento. Sullo scaffale entrano i domini dedicati con l'acquisto da pik.li e la gestione DNS, e l'ottimizzazione per newsletter e campagne di marketing aggressivo. Cosa manca ai piani e in che ordine farlo: docs/48.
- Base: i link durano tre giorni e l'API resta ai piani a pagamento — il listino lo diceva al contrario, con una spunta.
- Il modulo d'acquisto si accorcia da solo (docs/46): nome, privato o azienda (e per l'azienda ragione sociale e partita IVA, verificata su VIES), paese, e l'indirizzo solo se il paese è in Europa. L'elenco dei paesi è Europa per esteso, Stati Uniti e «fuori da Europa e Stati Uniti». L'IVA segue davvero il cliente: quattro regimi, la soglia OSS dei 10.000 € contata sui documenti emessi, le due prove sul paese annotate quando non concordano.
- Ordini di dominio: quello in attesa si può pagare, quello incassato porta alla ricevuta o alla fattura; il margine in amministrazione è misurato sul netto (scriveva 7,30 su un dominio che ne lascia 3,89). Un dominio registrato è del cliente che l'ha comprato, e solo lo staff può farci link oltre a lui.
- Le chiavi su staging non marcivano da sole: le cifravamo in due modi, a seconda di quando durante il boot qualcuno chiedeva l'encryptor. Forma fissata, forme vecchie leggibili, ripristino a ogni rilascio — che prima non girava, perché una frase fra virgolette in un commento chiudeva la stringa dello script.
- Safe Browsing acceso con la sua chiave; Turnstile tolto; URLhaus torna verde. Criptovalute: gateway adesso, nodo nostro più avanti (docs/49).
-
(sera) — Revisione su telefono
- Sessantacinque pagine misurate (docs/42) a 375, 390 e 768 px, in italiano e in arabo, nei due temi, con tre sessioni diverse. Corretta la causa unica dello scorrimento laterale — una cella di griglia CSS nasce larga quanto il suo contenuto, e bastava una tabella dentro una scheda per portarsi fuori schermo l'intera pagina: fino a 596 px in cinque pagine di amministrazione, e in due casi duecento pixel di tabella venivano tagliati via in silenzio invece di scorrere. Una riga nel foglio di stile invece di inseguire le viste una per una.
-
Il pannello della campanella nasceva per metà fuori dallo schermo a 375 px, e nessuna misura di scorrimento poteva accorgersene: sotto
smsi allinea all'intestazione e non più alla campanella. - Quattro registri da sette-nove colonne diventano schede su telefono, con la stessa tecnica già usata dal registro accessi, scritta una volta sola. In arabo il difetto era peggiore che in italiano, perché lo scorrimento parte dal lato opposto: nella scheda di un ordine si leggeva «0 €» al posto del totale.
- Aree di tocco a 44 px senza cambiare la grafica, campi a 16 px perché Safari non ingrandisca la pagina (e, ingrandendola, non produca proprio lo scorrimento che tutto il resto evita), distintivo del reCAPTCHA sollevato sopra la barra inferiore, bottoni dei filtri spostati dalla parte opposta al pulsante dei cookie.
-
(pomeriggio) — Fatture, ordini, campanella, reCAPTCHA
-
Fatture e ricevute (docs/37): chi paga riceve il documento da solo — fattura per le aziende con partita IVA, ricevuta per tutti gli altri. Numerazione annuale senza buchi presa sotto lock consultivo di PostgreSQL, dati del cliente e nostri congelati sulla riga al momento dell'emissione (una ristampa fra cinque anni dà la stessa carta), PDF in Prawn con l'impaginazione del gestionale che le fatture le fa già, e-mail con l'allegato nella lingua del destinatario, registro scaricabile in
/app/invoices. L'emissione è idempotente: un webhook che arriva due volte non produce due documenti. L'IVA è quella italiana per tutti, scorporata dall'incasso: semplificazione voluta, scritta come tale perché un commercialista la confermi prima di vendere fuori dall'Italia. -
Ordini in amministrazione (docs/38): ogni pagamento ha un numero da dire al telefono (
ORD-2026-000123). Elenco con ricerca, filtri e totali; scheda con cliente, righe, eventi del fornitore e documento; azioni per cambiare stato a mano con motivazione obbligatoria, marcare pagato (che attiva l'abbonamento ed emette il documento), marcare rimborsato, emettere il documento in ritardo. Tutto nel giornale delle modifiche. Aggiunto l'elenco di tutte le fatture emesse. - Disdetta che non toglie niente il giorno stesso (docs/38): chi disdice tiene il piano fino alla fine del periodo già pagato e scende dopo, per opera di un lavoro orario. Predisposti i rinnovi automatici: il ramo PayPal solleva un errore esplicito finché non ci sono le chiavi, e apre comunque l'ordine, così un rinnovo mancato si vede dall'elenco invece che dal cliente arrabbiato.
- Commissione del fornitore a carico di chi paga (docs/41 §6): calcolata al lordo, perché il fornitore trattiene la sua percentuale su quello che incassa davvero; visibile accanto al fornitore prima di scegliere e su una riga propria in fattura. Tariffe nelle impostazioni, da confrontare con l'estratto conto prima della produzione. Il paragrafo relativo è nei termini, in nove lingue.
-
Campanella e avvisi (docs/40, docs/32): dodici eventi in una tabella di notifiche con destinatario (utente o amministrazione), campanella nell'intestazione con conteggio dal vivo, pagina dedicata da venti per pagina con filtri e selezione multipla, pulizia automatica. Gli eventi spuntati in amministrazione partono anche su WhatsApp, fra questi il link che supera le mille aperture con chi, cosa, quanto e che tipo di sito. Le soglie si riconoscono da un solo
UPDATEche restituisce il contatore: due click simultanei non possono rivendicare la stessa. - reCAPTCHA sui moduli pubblici (docs/39): accesso, registrazione, registrazione rapida, recupero password, segnalazione di abuso e creazione del link. La chiave registrata è a punteggio, quindi la casella «non sono un robot» non si può disegnare e tutti i moduli usano la variante invisibile; il punteggio viene controllato, altrimenti la verifica sarebbe decorativa. Soglia a 0,3 e non a 0,5: una chiave così non offre nessuna sfida, e preferiamo far passare un bot che chiudere fuori un cliente. Se il fornitore non risponde si passa, e lo si scrive nel log.
- Accettazione dei termini registrata (docs/39 §2): nessuna casella da spuntare, per scelta, ma la frase è sopra il bottone ed è leggibile, e l'account conserva data e versione accettata, con la riga nel giornale. Versione e data dei testi legali vengono ora da un posto solo.
-
Difetti corretti: sulle pagine pubbliche la sessione non veniva mai letta, così chi era già entrato vedeva l'intestazione di uno sconosciuto (niente menu profilo, niente campanella, niente ultimi link); il modulo di segnalazione abusi buttava via quello che era stato scritto a ogni errore;
/abuseera l'unico modulo pubblico senza limite di frequenza; il token di reCAPTCHA finiva in chiaro nei log; dueUPDATEnon atomici sui contatori dei click. - Niente più promesse sulla pubblicità: tolte dalla pagina iniziale e dai termini in nove lingue. Il piano gratuito resta gratuito, ma non ci vincoliamo a non mostrare mai un annuncio.
- Marchi veri per i metodi di pagamento (Monero, Bitcoin, PayPal), serviti da noi con la licenza accanto ai file; nel selettore della lingua ogni riga segue la direzione della pagina, così in arabo le bandiere stanno a destra come tutto il resto.
-
Fatture e ricevute (docs/37): chi paga riceve il documento da solo — fattura per le aziende con partita IVA, ricevuta per tutti gli altri. Numerazione annuale senza buchi presa sotto lock consultivo di PostgreSQL, dati del cliente e nostri congelati sulla riga al momento dell'emissione (una ristampa fra cinque anni dà la stessa carta), PDF in Prawn con l'impaginazione del gestionale che le fatture le fa già, e-mail con l'allegato nella lingua del destinatario, registro scaricabile in
-
(mattina) — Font e librerie servite da noi
-
Niente più risorse da server terzi (docs/36): i caratteri Inter e JetBrains Mono non arrivano più da Google Fonts e
chart.jsnon arriva più da jsDelivr. Otto file woff2 (sottoinsiemi latino, latino esteso, cirillico e greco, font variabili: un file copre tutti i pesi) stanno inapp/assets/fonts/con le rispettive licenze SIL OFL, le regole@font-faceinapp/assets/stylesheets/fonts.css,chart.js4.5.0 e la sua unica dipendenza invendor/javascript/. Il guscio delle pagine non ha più né ipreconnectné il foglio di stile esterno: aprendo una pagina qualsiasi, prima di qualunque scelta sui cookie, il browser parla solo con noi. Circa 250 KB di caratteri in tutto. Arabo e cinese continuano a usare i font di sistema, come già facevano: portarli in casa costerebbe qualche megabyte per due lingue su nove. - Testi legali allineati nelle nove lingue: Google Fonts e jsDelivr tolti dall'elenco dei fornitori esterni nell'informativa cookie e nella tabella dei destinatari della privacy; le introduzioni ora dicono che caratteri e libreria dei grafici li serviamo noi. reCAPTCHA, Cloudflare e i fornitori di pagamento restano dove erano. Chiuso il rischio n. 2 di docs/27.
-
Niente più risorse da server terzi (docs/36): i caratteri Inter e JetBrains Mono non arrivano più da Google Fonts e
-
(notte, dopo) — Revisione finale
-
Revisione finale (docs/35): tutto il sito passato nel browser come utente e come amministratore, su telefono e desktop, nei due temi e in tre lingue, più una scansione delle nove lingue. Dodici difetti corretti: le pagine dei tab di un link perdevano intestazione e navigazione al ricaricamento; le strisce dei tab tagliavano le etichette su telefono (daisyUI 5 rende il
.tabrestringibile); il pulsante dei cookie copriva il menu laterale e la voce «Home» della barra inferiore nelle aree riservate; una bandiera mostrata come codice HTML nel filtro paese degli utenti admin; altri due frame che rispondevano consrca sé stessi (servizi del centro di controllo, esportazioni del registro accessi); tre icone inesistenti nel set della gem, con l'helper che ora ripiega su un'icona visibile; intestazione del link stretta su telefono; titolo SEO sbagliato in/app/help; grafia «URLhaus» nella pagina di stato.
-
Revisione finale (docs/35): tutto il sito passato nel browser come utente e come amministratore, su telefono e desktop, nei due temi e in tre lingue, più una scansione delle nove lingue. Dodici difetti corretti: le pagine dei tab di un link perdevano intestazione e navigazione al ricaricamento; le strisce dei tab tagliavano le etichette su telefono (daisyUI 5 rende il
-
(notte) — Domini e DNS, registro accessi, notifiche WhatsApp, e-mail, revisione legale
- Domini e DNS (docs/19): client Cloudflare e Internet.bs, creazione della zona con i record dei link e nameserver da consegnare al cliente, editor DNS in stile Cloudflare per utente e amministratore, job periodico che controlla puntamento, zona, registrar e liste di abuso, assegnazione di un dominio a un cliente e acquisto dal pannello con conferma digitata. Nell'area cliente non compare mai il nome dei fornitori: si parla di DNS gestito e di nameserver. In admin una fascia mostra lo stato dei due collegamenti con il credito del registrar, letta da valori memorizzati e mai sondata al caricamento della pagina.
- Registro degli accessi (docs/34): tabella dei click con identificativo pubblico leggibile, paese con bandiera, dispositivo, lingua e provenienza; ricerca, filtri, ordinamento e impaginazione sul database dentro un Turbo Frame, senza librerie esterne. Il conteggio è esatto fino a diecimila righe e stimato oltre, così resta in pochi millisecondi anche con centomila accessi; i riepiloghi pesanti sono precalcolati ogni tre minuti. Esportazione completa in foglio di calcolo preparata in coda. L'indirizzo IP non compare perché non viene conservato: si mostra l'impronta con la spiegazione.
- Geolocalizzazione (docs/30): il paese continua ad arrivare gratis da Cloudflare, città e regione dal database MaxMind GeoLite2 interrogato in locale, senza inviare l'indirizzo a nessuno. Aggiornamento automatico settimanale. Aggiunte 271 bandiere SVG servite da noi, con i nomi dei paesi: le bandiere emoji su Windows non esistono.
- Notifiche WhatsApp (docs/32): stesso contratto del progetto RIC, invio in coda con tre tentativi. Perché un messaggio parta servono due condizioni: canale acceso con numero configurato ed evento presente nell'elenco consentito. Collegate a segnalazione di abuso, link bloccato dai controlli automatici e nuovo account confermato.
- E-mail transazionali (docs/33): guscio unico a tabelle con colori scritti in linea, tema scuro su tre livelli, nessuna immagine (il marchio è disegnato in HTML), versione testuale scritta a mano per ogni messaggio, arabo impaginato da destra a sinistra. Aggiunta la disiscrizione con un clic dalle comunicazioni facoltative, come chiedono Gmail e Yahoo. Corretto l'identificativo del messaggio, che veniva costruito sul nome della macchina.
- QR e limiti per piano (docs/28): QR personalizzabile dai piani a pagamento con contrasto garantito e logo, bloccato con invito per il piano gratuito; statistiche e storico limitati senza inviare al browser i dati oscurati; le API servono il codice disegnato dal proprietario.
- Piani e fatturazione (docs/29): numeri accanto alle barre di consumo, descrizioni dei tre piani ricavate dalle funzioni reali, nota sulle commissioni PayPal calcolate al pagamento.
- Grafici e badge (docs/07 §0): scala di otto colori costruita sui token del tema, valore e percentuale al passaggio del mouse e al tocco, badge rifatti in modo centrale con colore coerente al significato.
- SEO (docs/21 §10): corretti tredici problemi, fra cui i gruppi di robots.txt che lasciavano liberi i crawler nelle aree private, canonical e hreflang che si contraddicevano, la sitemap non valida e i dati strutturati con offerte inventate.
- Revisione legale (docs/27): termini, privacy, informativa cookie e pagina per le autorità riscritti su quello che il software fa davvero, nelle nove lingue. Segnalati tre rischi che richiedono decisioni del committente.
-
Chiavi dei servizi (docs/25 §6): una chiave che non si decifra non viene più ricordata come mancante. Nuovo comando
pikli:reseal_credentialsper riscriverle dopo un cambio della chiave di cifratura. -
Difetti corretti: menu delle azioni in admin che non si apriva mai; fasce dei contatori sempre vuote per frame che puntavano a sé stessi; errore 500 sui domini dei link per ogni indirizzo terminante in
.xml; bandiere mostrate come codice HTML; quote a zero che bloccavano invece di significare illimitato; caselle degli eventi dei webhook tutte sulla stessa riga; controllo di Prompter che dichiarava guasto un servizio sano; suite di test che falliva a caso perché alcuni test riaccendevano i limiti di frequenza.
-
Chiavi configurabili, stato del servizio, SEO, stati account e API v1 ampliate
-
Chiavi dei servizi esterni configurabili dall'admin (docs/25): nuova tabella
app_credentialscon valore cifrato a riposo (MessageEncryptordasecret_key_base), servizioCredentialscome unico punto di lettura (database → ENV), pagina Impostazioni → Credenziali con le voci raggruppate, descrizione per ciascuna, maschera del valore salvato, rimozione e prova di connessione per servizio (Credentials::Tester). Nessun servizio legge piùENVper queste chiavi. Valori precaricati dal bloccoseed:delle credenziali cifrate tramitedb/seeds/credentials.rb, senza mai sovrascrivere ciò che l'admin ha salvato. -
Prompter collegato davvero (docs/06 §12): endpoint
POST /api/ai/links/evaluateimplementato nel progetto Prompter e pubblicato; lato pik.li indirizzohttps://ollama.incloud.srl:4001, certificato interno pinnato inconfig/certs/prompter.pem(verifica TLS attiva),PrompterClient.httpunico costruttore delle connessioni. Un verdetto di ripiego del modello (evaluated: false) finisce sempre in revisione umana e non viene più considerato "consentito". -
Pagina di stato rifatta (docs/20): tabelle
service_checkseservice_check_events, job ogni 5 minuti su sei servizi (API, servizio IA, server, pagamenti, Safe Browsing, URLhaus),ServiceStatusche legge solo dal database; pagina pubblica con stato complessivo, uptime 24 ore e 7 giorni, barra a segmenti con tooltip, aggiornamento automatico via Turbo Frame, tema chiaro/scuro e RTL; scheda "Servizi" in/admin/systemcon ricontrollo immediato. -
Home, header, footer e SEO (docs/21): descrizione della home allineata a sinistra, badge IA spostato sotto le statistiche, header a tutta larghezza con logo a sinistra e controlli a destra, colonna lingue tolta dal footer, firma "Created and Maintained by InCloud Srl", voce Police Cooperation con pagina dedicata nelle nove lingue; helper SEO con titoli, description, keyword, canonical, hreflang, Open Graph, Twitter card e JSON-LD,
robots.txtesitemap.xmllocalizzata,noindexsulle aree private. - Banner dei cookie: il partial esisteva ma non era incluso in nessun layout, quindi non è mai comparso. Ora è nel layout comune per tutte le facce tranne il redirect.
-
Stati account e chiave API dall'admin (docs/22): nuovi stati
inactiveeblockedcon durata a tempo o infinita (blocked_until,blocked_reason), riattivazione automatica alla scadenza da job e all'accesso, sessioni chiuse al blocco; menu delle azioni che esce dalla tabella (controller Stimulusmenu), avatar unificato con iniziali sensate e colore stabile, conferma e annullamento manuale dell'e-mail, scheda API per utente con chiave rivelabile (conservata cifrata), rigenerazione e abilitazione. -
API v1 ampliate (docs/23, docs/24): endpoint di servizio (
ping,limits), statistiche di account con confronto sul periodo precedente, link attivi nelle ultime 24 ore, filtri e viste sui link, conteggio, lookup, creazione in blocco con esito per riga, QR, elenco click, tag e webhook; errori uniformi localizzati, header di rate limit,Idempotency-Key, limite reale per chiave in rack-attack; documentazione pubblica riscritta e specifica OpenAPI 3.1 inpublic/openapi.json. - Posta: parametri SMTP e mittente letti dalle credenziali e applicati senza riavvio; record SPF, DKIM e DMARC di pik.li, dei domini dei link e dei domini dei clienti documentati in docs/26.
-
Correzioni: URLhaus non inviava mai l'intestazione
Auth-Key, quindi ogni controllo tornava vuoto in silenzio; le etichette del giornale delle modifiche non si traducevano perché scritte con chiavi puntate (79 voci per ognuna delle nove lingue); classe daisyUI 5 sbagliata sugli avatar (avatar placeholderinvece diavatar avatar-placeholder); test della barra di stato che falliva a ridosso del confine dei bucket.
-
Chiavi dei servizi esterni configurabili dall'admin (docs/25): nuova tabella
-
App Rails 8.1 online su staging
- Istanziata l'app (Rails 8.1, Hotwire, Tailwind 4 + daisyUI 5, PostgreSQL, Redis, Solid Queue) nella root del repo; modelli per utenti (e-mail o username, ricordami, stati, privato/azienda, piani base/premium/business, override per account), domini (pool per piano + custom), link, click, moderazione, segnalazioni, chiavi API, webhook, abbonamenti/pagamenti/eventi; seed con utenti e dati di prova.
- Flusso di registrazione rapida: nessun link senza account; e-mail + password (+ captcha quando ci saranno le chiavi), account "pending", link generato automaticamente alla conferma e-mail con aggiornamento live della pagina; dati di fatturazione richiesti solo all'acquisto.
- Quote e parametri: piano free 3 link al giorno; parametri globali per piano modificabili dall'admin con override per singolo account (limiti, feature, API); API v1 per Premium/Business, abilitabili globalmente anche ai Free (spento di default) e per account.
-
Redirect e tracking: 302 con no-store, anteprima
+, interstitial per link in verifica, password, 410/403/404; click asincroni con IP hashati, geo/device/referrer; moderazione con prefiltri + Safe Browsing/URLhaus + Prompter (mock) ogni 10 minuti. - Aree utente e admin complete (specifica docs/12): dashboard live, link con tab (statistiche, QR, impostazioni, storico, moderazione), analytics aggregate, tag, domini, API, webhook, billing mensile/annuale con provider, impostazioni, ricorsi; admin con dashboard KPI, coda moderazione live, regole, link, utenti (piano, stati, impersonificazione, limiti), domini, segnalazioni, abbonamenti, pagamenti, impostazioni, audit, salute sistema.
-
i18n: inglese predefinito con rilevamento del browser, nove lingue, selettore con bandierine, RTL per l'arabo, task
i18n:check; header con logo a sinistra e controlli a destra; badge IA amichevole; CTA scura; nessun riferimento alla "famiglia inCloud". -
Staging: https://staging.pik.li su staging.incloud.srl (utente dedicato, Redis dedicato, Solid Queue come servizio, nginx + certificato, mailbox protetta per le e-mail), script
deploy/staging/*; documentazione in docs/13, 14, 15. - Test: 74 test verdi. QA (docs/16): 19 difetti, 15 corretti subito (dropdown coperto, checkout che attivava piani gratis, contatori con bot, audit non tradotto, e-mail non localizzata, overflow mobile, quota su duplica, soglie moderazione, 404 brandizzato…), 4 in backlog.
-
Cookie policy e banner (categorie necessari/preferenze, policy completa, pagina /cookies) in nove lingue con logo pik.li; descrizione del servizio in home; fix spaziatura dei form (label
.form-control); valutazione "newsletter tracking" (docs/17).
-
Area utente: analitiche, moderazione, sessioni, billing, domini, API (agente area utente)
-
Analitiche aggregate
/app/analytics(U-ANL-01, R1): filtri periodo 7/14/30/90/personalizzato, dominio, tag, «includi bot»; KPI (click, unici, link con click, click per link); sei tab nel frametab_content(Panoramica con click+unici, Provenienze con «diretto», Geografia con città dietro paywall per il free, Dispositivi con tre doughnut e lingue, Orari con heatmap 7×24 in CSS grid, Top link con sparkline); banda «oltre la retention» con intervallo ridotto; export CSV peranalytics_full. Voce «Analitiche» nell'aside e nella bottom nav. -
Dettaglio link: tab Moderazione (U-LINK-06, R4) con card di stato verde/ambra/rossa, cronologia dei controlli (fonti tradotte), segnalazioni ricevute e form di ricorso (≥ 20 caratteri, un solo ricorso aperto, risposta Turbo Stream su
link_<id>_moderation); tab Analitiche con metrica click/unici, città (premium) e lingue, empty state con «Copia»; tab QR con PNG 256/512/1024 e SVG con lucchetto; tab Storico con diff prima→dopo dagliaudit_logse limite per piano; scadenza «dopo N click» e URL finale con UTM in Panoramica. -
Lista link: tab di stato Tutti/In revisione/Disattivati/Scaduti con conteggi, ordinamenti (click 7 gg, alfabetico, in scadenza), favicon e sparkline per riga, barra bulk sticky (Stimulus
bulk: tag/untag con featurebulk, disattiva, riattiva, esporta selezione, elimina), empty state per filtri; «Disattiva» risponde con toast e Annulla (partialapp/shared/_toastcon azioni); duplica in Turbo Stream; gating per piano dei campi (slug, password, scadenza, max click, UTM) con badge-lucchettofeature_lockche porta al paywall; tag da stringa separata da virgole (bug: la stringa finiva nel cast dell'array PG). -
Impostazioni a quattro tab: Profilo con paese, codice fiscale e blocco «Dati di fatturazione» (richiesti solo al checkout, banner
complete=1); Sicurezza con sessioni attive (browser/OS via DeviceDetector, IP mascherato, revoca singola e «Chiudi tutte le altre», R11aApp::SessionsController) e attività recente; Preferenze con lingua e tema a radio con anteprima immediata (Stimulustheme-pref); Privacy con export JSON di tutto l'account (R11b), retention, sub-responsabili e chiusura account con username digitato + password. -
Piano e fatturazione a tre tab: Piano e uso (card piano, barre link/click/domini/chiavi, storico 6 mesi, banda piano scaduto), Cambia piano (selettore mensile/annuale nel frame, radio dei provider disponibili + «Attivazione immediata (solo prova)» = provider
manualinBilling::Providers.for_checkout/Checkout.manual_activation, attivo in dev/test o conbilling.providers.manual.enabled;successcon toast e ritorno alla pagina di partenza), Fatture e pagamenti (ricevute Stripe). -
Domini: tab Domini di sistema (badge piano, «Nel tuo piano»/lucchetto, link creati, predefinito salvato in
users.settings["default_domain_id"]e usato daDomain.default_for) e I tuoi domini (record TXT/CNAME con copia, verifica, rimozione, paywall per il free). -
API e chiavi: tab Chiavi (token mostrato una volta, stato abilitazione, creazione bloccata se
api_enabled?è falso, max 10), Quota e consumo (rpm del piano, richieste per chiave), Documentazione con esempicurl. API v1: filtriq/tag/status, paginazione,expires_at/max_clicks/password/UTM con gating,stats?period=,mecon limiti e consumo,domainscondefault. -
Segnalazioni e appelli a quattro tab (link disattivati con stato ricorso, i miei ricorsi, segnalazioni ricevute per link senza dati del segnalante, cronologia verifiche); Tag con conteggio link/click, rinomina e rimozione su tutti i link (R6); Dashboard con selettore periodo (oggi/7/30, salvato in
settings["dash_period"]), delta vs periodo precedente, bande revisione/quota 80 %/100 %, top link del periodo, frame live con ultimo click; Importa ed esporta a tab (export CSV/JSON, import CSV con paywall). -
Infrastruttura:
SimpleCsv(la gemcsvnon è nel bundle di Ruby 3.4: export/import non funzionavano), scopeClick.for_user/heatmap/uniques_series,Link.in_review/disabled_any/expired/with_tag/on_domain,Domain.preferred_for/custom_limit_for, helperAppHelper(feature_lock,bars,expiry_text,session_device…), Stimulusdialog,bulk,theme-pref,tabs(aria + frecce),chartmulti-dataset,App::SearchController(R5, risultati per la palette). Locales in nuovi fileconfig/locales/app_extra.<locale>.ymlper le nove lingue;bin/rails i18n:checkinclude ora il prefissoapp_extra.. Test intest/controllers/app/*(26) + test auth riallineati ai controller reali.
-
Analitiche aggregate
-
Area admin: implementazione P0 + P1 facili (docs/12 §8)
-
Navigazione (A-NAV-01/02):
Navigation.admin_menuriorganizzato per sezioni (Panoramica, Moderazione e abusi, Link, Utenti, Domini, Sistema e job, Piani e fatturazione, Impostazioni + Audit log) con badge live sempre presenti nel DOM (nav_badge_<key>, nascosti a 0) aggiornati dal frameadmin_badges(30 s) e dai broadcast diAdmin::Live.admin_counters(canaleadmins, solo al cambio); bottom nav admin con FAB «Coda» al centro e badge live (admin/shared/_bottom_nav); barra ambiente e banner kill switch nel layout admin; permessican?inAdmin::BaseController(purge, sbanna, ruoli, sicurezza riservati al superadmin). -
Dashboard (A-DASH-01): fasce salute (SystemHealth cache 30 s) → lavoro da fare (coda, segnalazioni, ricorsi con prime 5 righe) → crescita (
Admin::Kpis, frameadmin_kpiscon refresh 15 s e push dopo il batch, periodo?period=1|7|30, grafici click umani/bot 14 gg, MRR, bot ratio, quota prefiltri, job falliti). -
Moderazione (A-MOD-01..06): coda con tab Da decidere / Priorità alta / Decise oggi (con Annulla) / Verdetti IA (filtri fonte/verdetto/periodo, riga di sintesi); verdetti live (rimozione card, toast, badge, pannello del link, toast all'utente); disattivazione con categoria + motivo;
POST /admin/moderation/test(R14) con i prefiltri a secco; liste (allowlist, blocklist, TLD, brand, slug riservati) normalizzate con audit added/removed; politica (soglie, interstitial anonimi, kill switch →Pipeline.decide, ultimo batch in cachemoderation:last_batch); segnalazioni?kind=abuse(Aperte/In lavorazione/Chiuse/Abusive) e ricorsi?kind=appeal(Aperti/Fuori SLA/Decisi) con presa in carico, disattiva-e-chiudi, archivia, abusiva, blocklist host, accogli/respingi (motivo obbligatorio) e toast all'utente; nuove segnalazioni/ricorsi in prepend live. -
Link (A-LINKS-01..04): tab Tutti/Anonimi/Segnalati/Disabilitati/In scadenza/Scaduti, ricerca
#id, filtri (dominio, stato, moderazione, proprietario, host, tag, click ≥, password, scadenza, periodo, ordinamento); dettaglio con tab Panoramica/Analytics (bot inclusi/esclusi)/Moderazione/Cronologia/Tecnico; disabilita con motivo, riabilita, ricontrolla (Moderation::Pipeline.recheck), elimina soft ed «Elimina definitivamente» (superadmin, slug digitato); bulk sincrono ≤ 200 (disabilita con motivo, riabilita, ricontrolla, blocklist host, elimina). -
Utenti (A-USERS-01..06): tab Tutti/Da confermare/Nuovi/Sospesi/Bannati/Staff, filtri piano/tipo/paese, menu ⋯ per riga; scheda con tab Profilo/Limiti e override (feature a checkbox)/Link/Piano e consumo/Moderazione (punteggio di fiducia)/Sicurezza (sessioni, «Chiudi tutte», reset password inviato dall'admin, chiavi API)/Cronologia; conferma, sospendi (motivo),
unsuspend(R15a), banna (link disattivati + chiavi revocate), sbanna (superadmin), cambia piano con scadenza e nota (abbonamento manuale, toast all'utente), impersonificazione con motivo e audit start/stop. - Domini (A-DOM-01/02): pool di sistema con modifica in dialog, ordine, default unico, per anonimi, dev only, disattiva/attiva, rimozione bloccata se ci sono link; tab Clienti con verifica DNS (R16), forza attivo con motivo, sospendi, rimuovi.
- Impostazioni (A-SET-01/04, A-COMM-01, A-BILL-01/02): Generali (stato servizio + banner con anteprima, registrazioni, TTL anonimi, API globali/free, e-mail abusi/supporto, soglia bot); Piani (tutti i parametri incluso link al giorno, feature, avviso annuale > 12×mensile, solo differenze dai default, ripristino); Provider (Stripe/PayPal/crypto/manuale con chiavi mancanti, URL webhook, eventi recenti, «Prova connessione» R19); Chiavi esterne mascherate; Sicurezza (superadmin).
- Abbonamenti e pagamenti (A-BILL-03/04): tab per stato, KPI, filtri, annulla con motivo (manuale → subito Base); pagamenti con filtri e totali, tab eventi webhook.
- Sistema (A-SYS-01..05, A-MOD-07): Servizi (frame live 30 s con dettagli DB/Redis/job/Prompter, stato dichiarato modificabile), Versione, Code e job (Solid Queue con retry/scarta R18, ricorrenti), Prompter (test URL), Feed, Cache (svuota), Database.
-
Audit log (A-AUDIT-01): tab Tutto/Staff/Impersonificazioni/Sistema/Distruttive, filtri attore (
me), azione, oggetto, periodo, testo; etichette tradotte (admin.audit.actions.*); nuove righe in prepend live. -
Modelli:
Report(statitriaged/spam, scope, SLA),AuditLog(scope, label, broadcast),User(lifecycle admin,FEATURE_KEYS,admin_change_plan!,trust_score),Subscription/Payment(scope, MRR),Setting(nuovi default,normalize_list,reset!). Servizi:Admin::Live,Admin::Kpis,SystemHealthesteso,Moderation::Pipeline.recheck+ kill switch,Moderation::Prefilter.test. Route admin:moderation/test,users/:id/unsuspend|reset_password|revoke_sessions,domains/:id/verify,system/jobs/:id/retry|discard,system/prompter/test,system/cache/clear,settings/providers/:key/test, aliasstatus/plans/audit. -
i18n: nuovi file
config/locales/admin_extra.<locale>.yml(en fonte + it, zh, ar, ru, fr, de, es, pt-BR, 670 chiavi con plurali corretti). Test:test/controllers/admin/*(33 test).
-
Navigazione (A-NAV-01/02):
-
Specifica implementativa delle funzioni
-
Scritto
docs/12-specifica-funzioni.md: 123 funzioni (11 fondamenta, 10 pubbliche, 6 autenticazione, 40 area utente, 50 area admin, 3 webhook pagamenti, 3 API) con id stabili, priorità P0/P1/P2 (72 P0 per l'anteprima), tab del main content, modelli e campi (esistenti vs migrazioni M1–M13), controller/route (5 route da aggiungere in P0, nessuna migrazione), comportamento live (canali, target DOM), catalogo dei toast IT, permessi/piano, stati di errore e criteri di accettazione per il QA; componenti UI condivisi, convenzioni Stimulus (17 controller), i18n, seed di prova, ordine di implementazione. -
Riconciliazioni con il codice: tre piani
free/premium/business(Starter e Pro dei doc 11 → premium), ruoliadmin/superadminin P0 (staff_rolein P1), nessuna organizzazione (workspace = utente), route esistenti con tab?tab=. Segnalati i bloccanti:LinkHostConstraintmancante,AccountMailere token di conferma assenti,schema.rbincompleto sulle colonne jsonb, registrazione senza statopending, reset password non inviato allarecovery_email. -
2026-09-22 — i18n: nove lingue, inglese predefinito. Estratte tutte le stringhe visibili (viste, controller, modelli,
Navigation, mailer, controller Stimulus viadata-*-value, redirect) inconfig/locales/en.yml(fonte, ~1.180 chiavi per areecommon/nav/public/auth/app/admin/toasts/mailers/models/redirects/errors/activerecord) e tradotte init,zh,ar(plurali a sei forme),ru(one/few/many/other),fr,de(du),es,pt-BR; tradotti anche iflow.<locale>.ymldel flusso di registrazione rapida. Selettore lingua con bandierine SVG (shared/_locale_switcher,FlagsHelper) nella nav pubblica, nella topbar app/admin, nel footer e nelle preferenze utente; nav pubblica riorganizzata (logo a sinistra, tutto il resto a destra, menu a tendina su mobile). Layout RTL per l'arabo con utility logiche di Tailwind edir="ltr"sui frammenti tecnici; pagine di redirect localizzate. Nomi dei piani tradotti con override admin (User.plan_label), badge e stati enum viaenum_label,SystemHealtha codici +health_label, toast live nella lingua del destinatario (Notifier.toast_t), formati zh da rails-i18nzh-CN(config/locales/zh_rails_i18n.rb). Nuovibin/rails i18n:check(chiavi, plurali, interpolazioni;lib/i18n_check.rb,test/i18n_test.rb) ebin/rails i18n:hardcoded(avviso). Modale di conferma daisyUI (#confirm_modal) al posto diconfirm(). Aggiornatodocs/13-locales.md.
-
Scritto
-
Revisione del committente: vincoli fase privata, logo, domini
- Piano operativo portato alla versione 2: fase privata a costo zero incrementale (server InCloud esistente, Cloudflare piano free, Workers/KV free tier opzionali, nessun billing), Safe Browsing v4 a uso privato + URLhaus al posto di Web Risk/Spamhaus finché il progetto non è commerciale, domini custom rimandati (Cloudflare for SaaS resta gratuito fino a 100 hostname anche sul piano free, verificato).
-
Logo deciso: nuvola di famiglia con "Pik.li" in Ganky, senza firma inCloud; palette ambra→corallo confermata. Set definitivo in
branding/logo/(marchio base con punto tipografico, variante punto-maglia, variante PIK.LI, mono e bianco, gemello Lnkz.li in ardesia e in ambra, favicon P/P./L, tavola e index.html,generate.pyrigenerabile); i 7 concept restano inbranding/proposals/come storico.docs/08apre con la sezione "Decisione del 2026-09-22". -
Scritto
docs/09-valutazione-pikli-lnkzli.md: confronto dei due domini e proposta "un prodotto, due volti" (pik.li pagina principale senza redirect, lnkz.li dominio dei link con seconda faccia minimale in tema ardesia, pool di domini all'apertura pubblica,pik.li/slugcome futura opzione premium). - Aggiunto in testa ai documenti 01, 04, 05, 06, 07 un riquadro di aggiornamento che rimanda ai vincoli del piano; README aggiornato.
-
Studi completati e piano operativo
-
Scritto
docs/00-piano-operativo.md: sintesi delle decisioni (stack, database, piani, moderazione IA, domini, brand), fasi 0-5 con settimane e consegne, budget, KPI, rischi, decisioni aperte per il committente, prossimi passi. -
docs/01-strategia-free-premium.md: piani Free/Starter €9/Pro €29/Business €89/Enterprise, value metric sui click tracciati, catalogo feature premium con tier e complessità, come i leader strutturano il business, GTM, unit economics, rischi, strategia domini con registrar e prezzi (sezioni normative rimosse su indicazione del committente). -
docs/02-analisi-competitor-funzionalita.md: 20+ shortener (commerciali, deep linking, link-in-bio, open source, italiani/europei), matrice comparativa, lacune di mercato, feature MVP vs premium; report grezzi dei sotto-agenti inresearch/. -
docs/03-analisi-mercato-seo.md: dimensione mercato (Italia 7 M$ 2025), keyword IT/EN con volumi e CPC, posizionamento competitor, tre scenari di budget (≈2.500 / 7.000 / 19.000 €/mese) con tempi e KPI, GEO/AI visibility, canali non-SEO, considerazioni sui domini.li. -
docs/04-scelta-piattaforma.md: confronto Elixir/Phoenix vs Rails 8.1 su 17 criteri con matrice pesata; raccomandazione Rails 8.1 + Tailwind + PostgreSQL con redirect all'edge (Cloudflare Worker + KV) e Solid Queue; piano di bootstrap con comandi e Gemfile. -
docs/05-architettura-backend-database.md: architettura di riferimento, valutazione PostgreSQL vs MongoDB vs ClickHouse vs Sphinx (esito: solo PostgreSQL 18 + Redis), hot path del redirect, short code, pipeline click, rate limit su cookie, Cloudflare for SaaS, macchina a stati della moderazione, ERD e DDL completo, capacità e costi. -
docs/06-integrazione-prompter-ai.md: contrattoPOST /api/ai/links/evaluate, fetch lato pik.li, prefiltri e feed (Web Risk, URLhaus, Spamhaus; scartati Safe Browsing/PhishTank/OpenPhish), job ogni 10 minuti, prompt completo, piano file per Prompter, roadmap IA, sicurezza. -
docs/07-ui-ux-temi-grafici.md: analisi di 9 competitor su desktop e mobile, temi grafici, design token e temi daisyUI, inventario di 48 pagine, wireframe, flusso "shorten in 3 secondi", PWA con share target, WCAG 2.2 AA, i18n, roadmap UI. -
docs/08-branding-logo.mdebranding/proposals/: 7 concept di logo (consigliato 03 "Nuvola e maglie", palette ambra→corallo), SVG/PNG, favicon, tavola comparativa,index.html, scriptgenerate.pyrigenerabile. -
Nota infrastrutturale: il router Zyxel dell'ufficio filtra via DNS
git22.ghosted.ws; push eseguito puntando ssh all'IP reale con verifica della host key nota. Da mettere in whitelist sul router.
-
Scritto
-
Avvio progetto e piano operativo
-
Creato il repository e la struttura iniziale (
docs/,branding/,research/), README e questo changelog. -
Copiati in
branding/reference/incloud/i loghi della famiglia InCloud (corporate, ITinCloud, RESTinCloud, PECinCloud, EdilCloud, Backup, Watcher, Agent Smith, proposta ShopinCloud con script generatore) e il font Ganky inbranding/reference/fonts/, presi daincloud.srlbranch main. - Avviati gli studi paralleli con agenti dedicati: analisi funzionalità competitor, analisi di mercato/SEO, architettura backend e database, scelta piattaforma (Phoenix vs Rails), strategia free/premium, UI/UX, integrazione IA con Prompter, studio logo.
- Semrush MCP risulta senza unità API: l'analisi di mercato usa navigazione web, Perplexity e Supermetrics.
-
Creato il repository e la struttura iniziale (