---
name: file_unique_name
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: pure
signature: "func FileUniqueName(originalName string) string"
description: "Genera un nombre de archivo unico combinando un UUID v4 con la extension sanitizada del nombre original. Evita colisiones y elimina problemas con caracteres especiales."
tags: [file, unique, name, uuid, upload, infra]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [path/filepath, strings, unicode, github.com/google/uuid]
params:
  - name: originalName
    desc: "nombre original del archivo (puede contener path, espacios, caracteres especiales)"
output: "nombre unico {uuid}.{ext} con extension sanitizada (alfanumerica, minusculas, max 16 chars). Si no hay extension retorna solo el UUID"
tested: true
tests: ["preserva extension comun como png", "convierte extension a minusculas", "remueve caracteres especiales en extension", "genera UUID sin extension si el archivo no tiene", "trunca extensiones extremadamente largas"]
test_file_path: "functions/infra/file_unique_name_test.go"
file_path: "functions/infra/file_unique_name.go"
---

## Ejemplo

```go
n1 := FileUniqueName("vacaciones.PNG")
// n1 = "a1b2c3d4-e5f6-7890-abcd-ef1234567890.png"

n2 := FileUniqueName("contrato sin extension")
// n2 = "f9b6c2d1-..."  (solo UUID)

n3 := FileUniqueName("malicious; rm -rf /.exe.txt")
// n3 = "{uuid}.txt"
```

## Notas

Marcada como `pure` por contrato (no hace I/O ni depende de estado mutable explicitamente), pero internamente la generacion del UUID v4 usa un PRNG por lo que el resultado NO es determinista. Esto es aceptable en la convencion del registry: la pureza se refiere a la ausencia de side effects observables (no escribe a disco, red, ni globals), no al determinismo bit a bit.

La extension se sanitiza para evitar:
- Path traversal en disco (ej: `../../etc/passwd`)
- Inyeccion de comandos en logs/UI
- Ambiguedad de filesystem entre mayus/minus
