Files
fn_registry/python/functions/infra/gsc_auth.md
T
egutierrez 763e06c127 feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-20 18:22:23 +02:00

83 lines
4.1 KiB
Markdown

---
name: gsc_auth
kind: function
lang: py
domain: infra
version: "1.0.0"
purity: impure
signature: "def gsc_auth(credentials_path: str = \"\", subject: str = \"\") -> object"
description: "Autentica contra la Google Search Console API v1 (searchconsole/webmasters) con una cuenta de servicio JSON. Lee el JSON de credentials_path o, si esta vacio, de la env var GSC_SA_JSON; lanza ValueError claro si falta. Usa service_account.Credentials.from_service_account_file con scope https://www.googleapis.com/auth/webmasters.readonly (solo lectura). subject opcional aplica with_subject(subject) para domain-wide delegation (normalmente vacio en GSC). Construye y retorna el objeto service de googleapiclient.discovery.build('searchconsole','v1', cache_discovery=False) listo para consumir por pull_gsc_search_analytics. Requiere google-api-python-client y google-auth."
tags: [seo, gsc, infra, google, search-console, auth, service-account]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [os, google.oauth2.service_account, googleapiclient.discovery]
params:
- name: credentials_path
desc: "ruta al JSON de la service account de GCP. Si esta vacio, se lee de la env var GSC_SA_JSON. Si tampoco existe, se lanza ValueError. El JSON es un secreto: resolver desde pass o una ruta fuera del repo, nunca commitear."
- name: subject
desc: "opcional. Email para domain-wide delegation (impersonation) via with_subject. Normalmente vacio en Search Console, donde la SA se anade directamente como usuario en GSC sin requerir delegation."
output: "object. El service de googleapiclient (googleapiclient.discovery.Resource) para la API 'searchconsole' v1, autenticado con scope webmasters.readonly y cache_discovery=False. Se pasa a funciones consumidoras como pull_gsc_search_analytics."
tested: true
tests:
- "test_build_se_llama_con_searchconsole_v1_y_cache_off"
- "test_credentials_se_cargan_con_scope_readonly"
- "test_fallback_a_env_var_gsc_sa_json"
- "test_subject_aplica_with_subject"
- "test_error_cuando_falta_credential"
test_file_path: "python/functions/infra/gsc_auth_test.py"
file_path: "python/functions/infra/gsc_auth.py"
---
## Ejemplo
```python
import sys
sys.path.insert(0, "python/functions")
from infra import gsc_auth
# Opcion A: ruta explicita al JSON de la service account
service = gsc_auth(credentials_path="/home/enmanuel/secrets/gsc-sa.json")
# Opcion B: leer la ruta de la env var GSC_SA_JSON
# export GSC_SA_JSON=/home/enmanuel/secrets/gsc-sa.json
service = gsc_auth()
# Verificar la autenticacion listando los sitios verificados:
sites = service.sites().list().execute()
print([s["siteUrl"] for s in sites.get("siteEntry", [])])
```
## Cuando usarla
Antes de `pull_gsc_search_analytics` (o cualquier llamada a la Search Console
API): la usas para obtener el objeto `service` autenticado una sola vez y
reutilizarlo en las consultas posteriores (Search Analytics, sitemaps, sites).
Es el punto de entrada del capability group `seo`.
## Gotchas
- **Impura**: lee un JSON del disco y construye un cliente HTTP de Google. No
es determinista ni componible en el nucleo puro.
- **Dar de alta la SA en Search Console**: el email de la service account debe
anadirse manualmente como usuario en Search Console > Settings > Users and
permissions (rol Restricted/Full). Sin esto la auth funciona pero las
consultas devuelven 403 / sitios vacios.
- **Habilitar la API**: la "Search Console API" debe estar habilitada en el
proyecto GCP de la service account (consola de APIs & Services). Si no, el
primer `.execute()` falla con un error de API deshabilitada.
- **El JSON de la SA es un secreto**: no commitear nunca. Guardarlo en `pass`
o en una ruta fuera del repo y pasar la ruta por `credentials_path` o la env
var `GSC_SA_JSON`.
- **`subject` casi siempre vacio**: domain-wide delegation solo aplica si
impersonas a un usuario de un dominio Workspace; en GSC lo normal es anadir
la SA directamente como usuario y dejar `subject=""`.
- **Dependencias**: requiere `google-api-python-client` y `google-auth` en el
venv. Ya estan en `python/pyproject.toml`.
## Capability growth log
(sin cambios — v1.0.0 inicial)