# Capability: browser-profiles

Catálogo operativo de los perfiles del navegador Chromium para investigaciones
multicuenta OSINT. Por cada perfil de Chromium (un `--profile-directory` dentro
de un user-data-dir) guarda **qué correo/cuentas usar, propósito, persona e
identidad de la investigación** y la nota del vault que lo documenta, y permite
**lanzar el perfil** listo para trabajar mostrando sus cuentas. La fuente de
verdad vive en el service `osint_db` (FastAPI + DuckDB, `http://127.0.0.1:8771`),
en las tablas `browser_profiles` + `browser_profile_accounts` (schema main,
pobladas solo por API, como `network_scans`). Estas funciones son clientes HTTP
finos a ese service.

**Regla de seguridad dura:** una cuenta guarda `secret_ref` — una **referencia**
al secreto (ej. `pass show osint/p1/gmail`), NUNCA la contraseña en claro. Ni el
service ni estas funciones almacenan o resuelven credenciales: `browser_profile_open`
solo expone el `secret_ref` para que el operador (o otra herramienta) lo resuelva
con `pass`/keepass.

Comparte el ecosistema del project `osint` (vault Obsidian + service `osint_db`)
con los grupos `recon`, `osint-passive` y `dav`. El perfil real de Chromium vive
en `~/.config/chromium-cdp` (user-data-dir con CDP 9222 inyectado por el wrapper
`/usr/bin/chromium`); el catálogo NO toca el perfil en disco, solo su metadata.

## Funciones

| ID | Firma | Qué hace |
|---|---|---|
| `browser_profile_register_py_browser` | `browser_profile_register(profile_dir, label="", persona="", purpose="", note_path="", tags=None, notes="", user_data_dir="", status="active", accounts=None, base_url=...) -> dict` | Registra/actualiza un perfil y, opcionalmente, sus cuentas en una sola llamada (1 POST del perfil + 1 POST por cuenta). Idempotente (upsert por `profile_dir` y por `id` de cuenta). `accounts` es una lista de dicts `{service, identity, secret_ref?, role?, status?, notes?}`. |
| `browser_profile_list_py_browser` | `browser_profile_list(status=None, base_url=...) -> dict` | Lista los perfiles del catálogo con su nº de cuentas (`n_accounts`). Filtro opcional por `status` (active/archived). Devuelve `{"status":"ok","profiles":[...]}`. |
| `browser_profile_show_py_browser` | `browser_profile_show(profile_dir, base_url=...) -> dict` | Muestra un perfil con todas sus cuentas. Devuelve `{"status":"ok","profile":{...},"accounts":[...]}` o error si no existe. Las cuentas traen `secret_ref` (referencia), nunca el password. |
| `browser_profile_open_py_browser` | `browser_profile_open(profile_dir, url=None, base_url=..., dry_run=False) -> dict` | Lanza Chromium en el perfil (`--profile-directory`) vía `systemd-run --user --scope` (evita exit-144) y devuelve sus cuentas/`secret_ref` para saber qué usar. `dry_run=True` devuelve el comando sin abrir nada. Compone `browser_profile_show` para leer la metadata. |

## Ejemplo canónico (end-to-end)

```python
import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from browser.browser_profile_register import browser_profile_register
from browser.browser_profile_list import browser_profile_list
from browser.browser_profile_show import browser_profile_show
from browser.browser_profile_open import browser_profile_open

# 1. Registrar un perfil con sus cuentas (secret_ref = referencia a pass, NO el password)
browser_profile_register(
    "osint_01",
    label="osint_01",
    persona="sock-puppet Marta R.",
    purpose="infiltración foros nicho X",
    tags=["osint", "sockpuppet"],
    accounts=[
        {"service": "gmail",    "identity": "marta.r.osint@gmail.com", "secret_ref": "pass show osint/osint_01/gmail", "role": "primary"},
        {"service": "twitter",  "identity": "@marta_r_osint",         "secret_ref": "pass show osint/osint_01/x",     "role": "burner"},
    ],
)

# 2. Listar el catálogo
browser_profile_list()                       # {"status":"ok","profiles":[{profile_dir, label, n_accounts, ...}]}

# 3. Ver un perfil con sus cuentas
browser_profile_show("osint_01")             # {"profile": {...}, "accounts": [{service, identity, secret_ref, role}]}

# 4. Abrir el perfil listo para trabajar (lanza Chromium + dice qué cuentas usar)
browser_profile_open("osint_01", url="https://twitter.com")
#   -> systemd-run --user --scope -- chromium --profile-directory=osint_01 https://twitter.com
#   -> accounts: [(gmail, pass show osint/osint_01/gmail), (twitter, pass show osint/osint_01/x)]
```

Vía `fn run` (un id conocido a la vez):

```bash
./fn run browser_profile_list
./fn run browser_profile_show osint_01
./fn run browser_profile_open osint_01 https://twitter.com
```

## Fronteras (qué NO cubre)

- **No gestiona el perfil de Chromium en disco** (crear/clonar/extensiones/avatar):
  eso es `create_chrome_profile_bash_browser`, `list_chrome_profiles_go_browser`,
  `set_chrome_profile_appearance_bash_browser`. Este grupo solo guarda metadata
  operativa y lanza un perfil existente.
- **No almacena ni resuelve contraseñas.** Solo referencias (`secret_ref`). El
  password se resuelve aparte con `pass`/keepass.
- **No automatiza el login** ni rellena formularios: para eso usa el `browser_mcp`
  o el grupo `flow-replay` una vez el perfil está abierto.
- **Requiere el service `osint_db` vivo** en `:8771`. Si está caído, las funciones
  devuelven `{"status":"error", ...}` sin lanzar.

## Gotchas

- El `profile_dir` es el nombre del directorio REAL del perfil de Chromium (lo
  que va en `--profile-directory`): `"Default"`, `"Profile 1"`, `"osint_01"`. NO
  es el nombre legible (ese es `label`). Verlos con
  `list_chrome_profiles_go_browser` o el `Local State` del user-data-dir.
- `browser_profile_open` por defecto NO pasa `--user-data-dir` (el perfil vive en
  `~/.config/chromium-cdp`, que el wrapper `/usr/bin/chromium` ya inyecta). Si el
  perfil está en otro user-data-dir, regístralo con `user_data_dir=<ruta>` y la
  función lo pasará explícito.
- Se lanza vía `systemd-run --user --scope` a propósito: lanzar Chromium directo
  desde un proceso hijo da exit-144 en este entorno.
- `secret_ref` NUNCA es el password. Si te ves tentado a meter la contraseña ahí,
  para: guárdala en `pass`/keepass y referencia el comando.
