From 381149e27656f7db60a3f3c764040e77d3270275 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Tue, 28 Apr 2026 14:24:57 -0500 Subject: [PATCH 1/6] Barra de ayuda contextualizada --- .../v1/modules/core/help_center/schemas.py | 8 + .../v1/modules/core/help_center/services.py | 30 +- frontend/src/lib/api/help.ts | 2 + .../src/lib/components/help/HelpDrawer.svelte | 342 ++++++++++++------ .../keyboard/KeyboardManager.svelte | 11 + .../src/lib/components/sidebar/modules.ts | 5 +- .../routes/dashboard/help-center/+page.svelte | 11 +- .../help-center/editor/[uuid]/+page.svelte | 24 +- 8 files changed, 299 insertions(+), 134 deletions(-) diff --git a/backend/api/v1/modules/core/help_center/schemas.py b/backend/api/v1/modules/core/help_center/schemas.py index 5fc67a37..065e9132 100644 --- a/backend/api/v1/modules/core/help_center/schemas.py +++ b/backend/api/v1/modules/core/help_center/schemas.py @@ -14,6 +14,8 @@ class HelpArticleBase(BaseModel): file_url: Optional[str] = None file_size: Optional[int] = None mime_type: Optional[str] = None + context_path: Optional[str] = None + tags: Optional[str] = None class HelpArticleCreate(HelpArticleBase): pass @@ -29,6 +31,8 @@ class HelpArticleUpdate(BaseModel): file_url: Optional[str] = None file_size: Optional[int] = None mime_type: Optional[str] = None + context_path: Optional[str] = None + tags: Optional[str] = None class HelpArticleInDB(HelpArticleBase): uuid: UUID @@ -50,6 +54,8 @@ class HelpSyncRequest(BaseModel): client_file_url: Optional[str] = None client_file_size: Optional[int] = None client_mime_type: Optional[str] = None + client_context_path: Optional[str] = None + client_tags: Optional[str] = None class HelpSyncResponse(BaseModel): status: str @@ -63,4 +69,6 @@ class HelpSyncResponse(BaseModel): server_file_url: Optional[str] = None server_file_size: Optional[int] = None server_mime_type: Optional[str] = None + server_context_path: Optional[str] = None + server_tags: Optional[str] = None message: str diff --git a/backend/api/v1/modules/core/help_center/services.py b/backend/api/v1/modules/core/help_center/services.py index 8f6f36cb..06b0ccff 100644 --- a/backend/api/v1/modules/core/help_center/services.py +++ b/backend/api/v1/modules/core/help_center/services.py @@ -22,6 +22,8 @@ class HelpCenterService: article.file_url = metadata.get("file_url") article.file_size = metadata.get("file_size") article.mime_type = metadata.get("mime_type") + article.context_path = metadata.get("context_path") + article.tags = metadata.get("tags") # Remove metadata from content for clean display if needed, # but usually better to leave it and let parser handle it or hide it here. # For now, we just set the attributes. @@ -32,6 +34,8 @@ class HelpCenterService: article.file_url = None article.file_size = None article.mime_type = None + article.context_path = None + article.tags = None return article @@ -44,7 +48,9 @@ class HelpCenterService: "content_type": data.get("content_type", "article"), "file_url": data.get("file_url"), "file_size": data.get("file_size"), - "mime_type": data.get("mime_type") + "mime_type": data.get("mime_type"), + "context_path": data.get("context_path"), + "tags": data.get("tags") } # Only append if there's something meaningful beyond "article" @@ -82,7 +88,7 @@ class HelpCenterService: # Move metadata into content data["content"] = HelpCenterService._extract_metadata(data["content"], data) # Remove virtual fields from data to avoid SQLAlchemy errors - virtual_fields = ["content_type", "file_url", "file_size", "mime_type"] + virtual_fields = ["content_type", "file_url", "file_size", "mime_type", "context_path", "tags"] for f in virtual_fields: if f in data: del data[f] @@ -105,16 +111,18 @@ class HelpCenterService: update_data = article_data.model_dump(exclude_unset=True) # Handle metadata update - if "content" in update_data or any(f in update_data for f in ["content_type", "file_url", "file_size", "mime_type"]): + if "content" in update_data or any(f in update_data for f in ["content_type", "file_url", "file_size", "mime_type", "context_path", "tags"]): # Merge existing metadata with new updates current_meta = { "content_type": getattr(db_article, "content_type", "article"), "file_url": getattr(db_article, "file_url", None), "file_size": getattr(db_article, "file_size", None), - "mime_type": getattr(db_article, "mime_type", None) + "mime_type": getattr(db_article, "mime_type", None), + "context_path": getattr(db_article, "context_path", None), + "tags": getattr(db_article, "tags", None) } # Update with new data if present - for f in ["content_type", "file_url", "file_size", "mime_type"]: + for f in ["content_type", "file_url", "file_size", "mime_type", "context_path", "tags"]: if f in update_data: current_meta[f] = update_data[f] @@ -123,7 +131,7 @@ class HelpCenterService: update_data["content"] = HelpCenterService._extract_metadata(content, current_meta) # Remove virtual fields from data - virtual_fields = ["content_type", "file_url", "file_size", "mime_type"] + virtual_fields = ["content_type", "file_url", "file_size", "mime_type", "context_path", "tags"] for f in virtual_fields: if f in update_data: del update_data[f] @@ -162,7 +170,9 @@ class HelpCenterService: "content_type": sync_data.client_content_type, "file_url": sync_data.client_file_url, "file_size": sync_data.client_file_size, - "mime_type": sync_data.client_mime_type + "mime_type": sync_data.client_mime_type, + "context_path": sync_data.client_context_path, + "tags": sync_data.client_tags } content_with_meta = HelpCenterService._extract_metadata(sync_data.client_content, client_meta) @@ -197,7 +207,9 @@ class HelpCenterService: "content_type": sync_data.client_content_type, "file_url": sync_data.client_file_url, "file_size": sync_data.client_file_size, - "mime_type": sync_data.client_mime_type + "mime_type": sync_data.client_mime_type, + "context_path": sync_data.client_context_path, + "tags": sync_data.client_tags } db_article.content = HelpCenterService._extract_metadata(sync_data.client_content, client_meta) db_article.title = sync_data.client_title @@ -232,6 +244,8 @@ class HelpCenterService: server_file_url=getattr(db_article, "file_url", None), server_file_size=getattr(db_article, "file_size", None), server_mime_type=getattr(db_article, "mime_type", None), + server_context_path=getattr(db_article, "context_path", None), + server_tags=getattr(db_article, "tags", None), message="Client is outdated. Update required." ) diff --git a/frontend/src/lib/api/help.ts b/frontend/src/lib/api/help.ts index e4907ccf..28c8443d 100644 --- a/frontend/src/lib/api/help.ts +++ b/frontend/src/lib/api/help.ts @@ -39,6 +39,8 @@ export interface HelpArticle { file_url?: string; file_size?: number; mime_type?: string; + context_path?: string; + tags?: string; } export const helpApi = { diff --git a/frontend/src/lib/components/help/HelpDrawer.svelte b/frontend/src/lib/components/help/HelpDrawer.svelte index 3d31f312..ad3f6a84 100644 --- a/frontend/src/lib/components/help/HelpDrawer.svelte +++ b/frontend/src/lib/components/help/HelpDrawer.svelte @@ -1,17 +1,28 @@ - - - - - - - {#if selectedArticle} - - {/if} - Base de Conocimientos - - - -
- {#if !selectedArticle} -
-
-

Artículos Disponibles

- {#if isAdmin} - - {/if} -
- {#if isLoading} -

Cargando...

- {:else if articles.length === 0} -

- No hay artículos de ayuda disponibles. -

- {/if} -
- {#each articles as article (article.uuid)} - - {/each} -
+ + +
+
+
+
+
- {:else} -
- {#if isEditing} -
- - -
-
+
+

Manuales y guías interactivas del sistema.

+
+ +
+ {#if !selectedArticle} + +
+ +
+ + +
+ + + {#if contextualArticles.length > 0 && !searchTerm} +
+
+ Recomendado para esta pantalla +
+
+ {#each contextualArticles as article} + - +
+ +
+
+

{article.title}

+

{article.category || 'General'}

+
+ + {/each} +
+
+ {/if} + + +
+

Guías Disponibles

+ {#if isLoading} +
+
+
+ {:else if filteredArticles.length === 0} +
+ +

No encontramos nada que coincida con tu búsqueda.

+
+ {:else} +
+ {#each filteredArticles as article} + + {/each} +
+ {/if} +
+
+ + +
+
+ + {#if isAdmin} + + {/if} +
+
+ {:else} + +
+
+ + {#if isAdmin && !isEditing} + + {/if} +
+ +
+ {#if isEditing} +
+
+ + +
+
+ + +
+
+ +
{:else} -
-
-

{selectedArticle.title}

- {#if isAdmin} - - {/if} +
+
+ {selectedArticle.category || 'General'} +

{selectedArticle.title}

+
+ Por {selectedArticle.last_editor} + + Actualizado: {new Date(selectedArticle.updated_at).toLocaleDateString()} +
-
+ +
{#if browser} {@html renderMarkdown(selectedArticle.content)} {:else} @@ -224,11 +320,17 @@
{/if}
- {/if} -
+
+ {/if} +
diff --git a/frontend/src/lib/components/keyboard/KeyboardManager.svelte b/frontend/src/lib/components/keyboard/KeyboardManager.svelte index c27c4017..1e3720b0 100644 --- a/frontend/src/lib/components/keyboard/KeyboardManager.svelte +++ b/frontend/src/lib/components/keyboard/KeyboardManager.svelte @@ -5,6 +5,7 @@ import { GLOBAL_NAV } from '$lib/config/shortcuts'; import { shortcutStore, activeShortcutsList } from '$lib/stores/shortcut-store'; import { focusStore, interactionMode } from '$lib/stores/focus-store'; + import { helpStore } from '$lib/stores/help.svelte'; import ShortcutsHelpModal from './ShortcutsHelpModal.svelte'; let showHelp = $state(false); @@ -334,6 +335,16 @@ return; } + // 1.5 HELP DRAWER: F12 + if (key === 'F12') { + if (!authenticated) { + return; + } + event.preventDefault(); + helpStore.toggle(); + return; + } + // 2. ESCAPE if (key === 'Escape') { if (showHelp) { diff --git a/frontend/src/lib/components/sidebar/modules.ts b/frontend/src/lib/components/sidebar/modules.ts index d1b6d33f..d040c051 100644 --- a/frontend/src/lib/components/sidebar/modules.ts +++ b/frontend/src/lib/components/sidebar/modules.ts @@ -18,6 +18,7 @@ import { Ship, Truck, Users, + Book, } from '@lucide/svelte'; import { m } from '$lib/i18n/messages'; import { Title } from '../ui/alert'; @@ -571,9 +572,9 @@ export function getSidebarData(): SidebarData { icon: Settings2, }, { - name: m["sidebar.reference_data.ayuda"](), + name: "Manuales del Sistema", url: "/dashboard/help-center", - icon: Frame, + icon: Book, }, ], }; diff --git a/frontend/src/routes/dashboard/help-center/+page.svelte b/frontend/src/routes/dashboard/help-center/+page.svelte index af307a74..9141a24f 100644 --- a/frontend/src/routes/dashboard/help-center/+page.svelte +++ b/frontend/src/routes/dashboard/help-center/+page.svelte @@ -56,7 +56,7 @@ order: 0 }); - // Derived state: Grouped by Category + // Derived state: Grouped by Category with prioritization for Manuals const groupedArticles = $derived.by(() => { const filtered = articles .filter( @@ -65,7 +65,14 @@ a.content.toLowerCase().includes(searchTerm.toLowerCase()) || (a.category || 'General').toLowerCase().includes(searchTerm.toLowerCase()) ) - .sort((a, b) => (a.order || 0) - (b.order || 0)); // Sort by order first + .sort((a, b) => { + // Prioritize Manuales category + const catA = (a.category || 'General').toLowerCase(); + const catB = (b.category || 'General').toLowerCase(); + if (catA.includes('manual') && !catB.includes('manual')) return -1; + if (!catA.includes('manual') && catB.includes('manual')) return 1; + return (a.order || 0) - (b.order || 0); + }); const groups: Record = {}; filtered.forEach((article) => { diff --git a/frontend/src/routes/dashboard/help-center/editor/[uuid]/+page.svelte b/frontend/src/routes/dashboard/help-center/editor/[uuid]/+page.svelte index d8ea7064..f807b354 100644 --- a/frontend/src/routes/dashboard/help-center/editor/[uuid]/+page.svelte +++ b/frontend/src/routes/dashboard/help-center/editor/[uuid]/+page.svelte @@ -21,7 +21,8 @@ FileText, Video as VideoIcon, FileCode, - Upload + Upload, + HelpCircle } from 'lucide-svelte'; import { toast } from 'svelte-sonner'; import { marked } from 'marked'; @@ -56,6 +57,8 @@ let file_url = $state(''); let file_size = $state(undefined); let mime_type = $state(''); + let context_path = $state(''); + let tags = $state(''); // Preview State let showPreview = $state(true); @@ -88,6 +91,8 @@ file_url = article.file_url || ''; file_size = article.file_size ?? undefined; mime_type = article.mime_type || ''; + context_path = article.context_path || ''; + tags = article.tags || ''; } } catch (e: any) { toast.error('Error al cargar artículo: ' + e.message); @@ -109,7 +114,9 @@ content_type, file_url, file_size, - mime_type + mime_type, + context_path, + tags }; // Auto-generate slug if missing @@ -300,6 +307,19 @@
+
+ + +

Expresión regular para activar este artículo en pantallas específicas.

+
+
+ + +

Separadas por comas. Ayudan a la búsqueda y contextualización.

+
From 97de088b5d19e992c2da5e23ad921d72f5f61454 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Wed, 29 Apr 2026 10:25:16 -0500 Subject: [PATCH 2/6] sistema contextual y de reocmendaciones de manuales, asi como busqueda y nuevps disenios --- .../v1/modules/core/help_center/services.py | 5 +- frontend/messages/en.json | 1 + frontend/messages/es.json | 1 + .../src/lib/components/help/HelpDrawer.svelte | 242 ++++++++++++++---- .../src/lib/components/sidebar/modules.ts | 2 +- .../help-center/editor/[uuid]/+page.svelte | 60 +++-- frontend/vite.config.ts | 2 +- 7 files changed, 239 insertions(+), 74 deletions(-) diff --git a/backend/api/v1/modules/core/help_center/services.py b/backend/api/v1/modules/core/help_center/services.py index 06b0ccff..e31921bc 100644 --- a/backend/api/v1/modules/core/help_center/services.py +++ b/backend/api/v1/modules/core/help_center/services.py @@ -54,7 +54,10 @@ class HelpCenterService: } # Only append if there's something meaningful beyond "article" - if metadata["content_type"] != "article" or metadata["file_url"]: + if (metadata["content_type"] != "article" or + metadata["file_url"] or + metadata["context_path"] or + metadata["tags"]): content += f"\n\n" return content diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 3b1e30d2..5414a941 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -3,6 +3,7 @@ "hello_world": "Hello, {name} from en!", "sidebar": { "dashboard": "Dashboard", + "help_center": "System Manuals", "reference_data": { "title": "Fixed Catalogs", "codes_pedimento_regimen": "Pedimento and Regime Codes", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index 6ecb0021..d17d7d5f 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -3,6 +3,7 @@ "hello_world": "Hello, {name} from es!", "sidebar": { "dashboard": "Dashboard", + "help_center": "Manuales del Sistema", "reference_data": { "title": "Catálogos Fijos", "codes_pedimento_regimen": "Códigos de Pedimento y Régimen", diff --git a/frontend/src/lib/components/help/HelpDrawer.svelte b/frontend/src/lib/components/help/HelpDrawer.svelte index ad3f6a84..0c7d8f14 100644 --- a/frontend/src/lib/components/help/HelpDrawer.svelte +++ b/frontend/src/lib/components/help/HelpDrawer.svelte @@ -14,6 +14,7 @@ Search, Sparkles, FileCode, + FileText, Upload } from 'lucide-svelte'; import { toast } from 'svelte-sonner'; @@ -34,18 +35,109 @@ let searchTerm = $state(''); const isAdmin = $derived($currentUser?.roles?.includes('admin') || false); - const currentPath = $derived(page.url.pathname); + const currentPath = $derived(page.url.pathname + page.url.search); - // Filtrar artículos contextuales basados en la ruta actual + const synonyms: Record = { + 'users': ['usuario', 'colaborador', 'acceso', 'perfil', 'permiso', 'roles'], + 'company': ['empresa', 'compania', 'negocio', 'fiscal', 'emisor', 'razon social', 'rfc'], + 'invoices': ['factura', 'cobro', 'gasto', 'cxc', 'cxp', 'comprobante', 'imp', 'exp', 'facturacion'], + 'packages': ['bulto', 'embalaje', 'empaque', 'pallet', 'contenedor', 'packing'], + 'audit': ['auditoria', 'bitacora', 'log', 'historial', 'evento', 'monitoreo'], + 'pedimentos': ['pedimento', 'aduana', 'valida', 'despacho', 'pedimentacion'], + 'parts': ['parte', 'mercancia', 'producto', 'fraccion', 'item', 'articulo', 'numero de parte'], + 'goods': ['mercancia', 'producto', 'bienes', 'parte', 'item'], + 'manifest': ['manifiesto', 'salida', 'embarque', 'transporte', 'carga'], + 'clients': ['cliente', 'proveedor', 'vendor', 'provider', 'comercial', 'socio', 'proveedores', 'clientes'], + 'transporters': ['transportista', 'fletera', 'chofer', 'conductor', 'camion', 'vehiculo', 'transporte'], + 'settings': ['configuracion', 'ajuste', 'preferencia', 'perfil', 'cuenta'], + 'digitalizacion': ['documento', 'archivo', 'digital', 'expediente', 'pdf', 'xml', 'e-document'], + 'reports': ['reporte', 'estadistica', 'grafica', 'consulta', 'descarga', 'excel', 'kpi'], + 'fractions': ['fraccion', 'arancel', 'nico', 'tarifa', 'impuesto', 'tigie'], + 'reference': ['catalogo', 'fijo', 'referencia', 'maestro', 'base'] + }; + + function getKeywords(str: string): string[] { + const isEdit = str.toLowerCase().includes('/edit') || str.toLowerCase().includes('/editor'); + const isCreate = str.toLowerCase().includes('/create') || str.toLowerCase().includes('/new'); + + const baseKeywords = str + .toLowerCase() + .normalize("NFD").replace(/[\u0300-\u036f]/g, "") // Quitar acentos + .replace(/[/_-]/g, ' ') + .split(/\s+/) + .filter(w => w.length > 2 && !['dashboard', 'general', 'catalogs', 'information', 'management'].includes(w)); + + if (isEdit) baseKeywords.push('edicion', 'editar', 'modificar', 'actualizar'); + if (isCreate) baseKeywords.push('crear', 'nuevo', 'registro', 'alta'); + + // Expandir con sinónimos + const expanded = [...baseKeywords]; + baseKeywords.forEach(kw => { + if (synonyms[kw]) expanded.push(...synonyms[kw]); + // Buscar si la palabra clave es un sinónimo de alguna categoría + Object.entries(synonyms).forEach(([key, values]) => { + if (values.includes(kw)) expanded.push(key); + }); + }); + return [...new Set(expanded)]; + } + + $inspect('HELP_DEBUG_PATH', currentPath); + $inspect('HELP_DEBUG_KEYWORDS', getKeywords(currentPath)); + + // Filtrar artículos contextuales basados en la ruta actual o coincidencias inteligentes const contextualArticles = $derived( articles.filter((a) => { - if (!a.context_path) return false; - try { - const regex = new RegExp(a.context_path); - return regex.test(currentPath); - } catch { - return currentPath.includes(a.context_path); + // 1. Prioridad: Ruta explícita (si existe) + if (a.context_path) { + try { + if (a.context_path.startsWith('/')) { + if (currentPath === a.context_path || currentPath.startsWith(a.context_path + '/')) return true; + } else { + const regex = new RegExp(a.context_path); + if (regex.test(currentPath)) return true; + } + } catch { + if (currentPath.includes(a.context_path)) return true; + } } + + // 2. Inteligencia de Coincidencia (Fuzzy match por palabras clave) + const editIntents = ['edicion', 'editar', 'modificar', 'actualizar', 'corregir', 'edit', 'editor']; + const createIntents = ['crear', 'nuevo', 'registro', 'alta', 'create', 'new']; + const intentionWords = [...editIntents, ...createIntents, 'baja', 'cambio']; + + const pathKeywords = getKeywords(currentPath); + const moduleKeywords = pathKeywords.filter(pk => !intentionWords.includes(pk)); + const pathIntentKeywords = pathKeywords.filter(pk => intentionWords.includes(pk)); + + const titleKeywords = getKeywords(a.title); + const contentKeywords = getKeywords(a.content.substring(0, 100)); + + // Si estamos en un módulo específico (ej. Pedimentos), DEBE coincidir el módulo + const matchesModule = moduleKeywords.length === 0 || moduleKeywords.some(pk => + titleKeywords.some(tk => tk.includes(pk) || pk.includes(tk)) || + contentKeywords.some(ck => ck.includes(pk) || pk.includes(ck)) + ); + + if (!matchesModule) return false; + + // Si hay una intención clara en la URL (crear/editar), filtramos los artículos + // que sean explícitamente de la intención OPUESTA. + if (pathIntentKeywords.length > 0) { + const pathIsEdit = pathIntentKeywords.some(pk => editIntents.includes(pk)); + const pathIsCreate = pathIntentKeywords.some(pk => createIntents.includes(pk)); + + const articleIsEdit = titleKeywords.some(tk => editIntents.includes(tk)); + const articleIsCreate = titleKeywords.some(tk => createIntents.includes(tk)); + + // Bloqueo cruzado: Si estoy creando, no me des manuales que son SOLO de editar. + // (Si el manual sirve para ambos o es general, pasará) + if (pathIsCreate && articleIsEdit && !articleIsCreate) return false; + if (pathIsEdit && articleIsCreate && !articleIsEdit) return false; + } + + return true; }) ); @@ -87,7 +179,7 @@ function startCreate() { editContent = '# Nuevo Artículo\nEscribe el contenido aquí...'; - editTitle = ''; + editTitle = 'Nueva Guía de Ayuda'; isEditing = true; isCreating = true; selectedArticle = { @@ -107,6 +199,7 @@ const newArticle = await helpApi.createArticle({ title: editTitle, content: editContent, + context_path: currentPath, // Captura automática de la ruta real last_editor: $currentUser?.username || 'unknown' }); selectedArticle = newArticle; @@ -144,6 +237,13 @@ .replace(/\*(.*)\*/gim, '$1') .replace(/\n/gim, '
'); } + + function highlightText(text: string, term: string) { + if (!term || term.length < 2) return text; + const escapedTerm = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const regex = new RegExp(`(${escapedTerm})`, 'gi'); + return text.replace(regex, '$1'); + } @@ -176,20 +276,26 @@ />
- + {#if contextualArticles.length > 0 && !searchTerm}
- Recomendado para esta pantalla +
+ Recomendado para ti +
{#each contextualArticles as article} + {/if}
{:else} -
- {#each filteredArticles as article} - +
+ {:else} +
+ {#each displayList as article} +
- {article.category || 'Gral'} - - {/each} -
+ + + {/each} +
+ {/if} {/if}
@@ -311,10 +445,20 @@
- {#if browser} - {@html renderMarkdown(selectedArticle.content)} + {#if selectedArticle.content_type === 'pdf' && selectedArticle.file_url} +
+ +
{:else} -
{selectedArticle.content}
+ {#if browser} + {@html renderMarkdown(selectedArticle.content)} + {:else} +
{selectedArticle.content}
+ {/if} {/if}
diff --git a/frontend/src/lib/components/sidebar/modules.ts b/frontend/src/lib/components/sidebar/modules.ts index d040c051..6cadef43 100644 --- a/frontend/src/lib/components/sidebar/modules.ts +++ b/frontend/src/lib/components/sidebar/modules.ts @@ -572,7 +572,7 @@ export function getSidebarData(): SidebarData { icon: Settings2, }, { - name: "Manuales del Sistema", + name: m["sidebar.help_center"](), url: "/dashboard/help-center", icon: Book, }, diff --git a/frontend/src/routes/dashboard/help-center/editor/[uuid]/+page.svelte b/frontend/src/routes/dashboard/help-center/editor/[uuid]/+page.svelte index f807b354..d0a3b428 100644 --- a/frontend/src/routes/dashboard/help-center/editor/[uuid]/+page.svelte +++ b/frontend/src/routes/dashboard/help-center/editor/[uuid]/+page.svelte @@ -74,7 +74,11 @@ const uuid = $page.params.uuid as string; if (uuid === 'new') { loading = false; - // Defaults for new article + // Pre-rellenar context_path si viene en la URL + const urlParams = new URLSearchParams(window.location.search); + if (urlParams.has('context_path')) { + context_path = urlParams.get('context_path') || ''; + } return; } @@ -286,6 +290,11 @@ +
+ + +

Se autogenera del título si se deja vacío.

+
-
- - -
-
- - -
-
- - -

Expresión regular para activar este artículo en pantallas específicas.

-
-
- - -

Separadas por comas. Ayudan a la búsqueda y contextualización.

-
+ +
+ + Opciones Avanzadas + + +
+
+ + +
+
+ + +
+
+ + +

URL donde aparecerá este artículo.

+
+
+ + +
+
+
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 5346ce8c..c9ac8ce9 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -51,7 +51,7 @@ export default defineConfig({ // 'otro-host.com' si necesitas más ], proxy: { - '/api/uploads': { + '/api': { target: 'http://backend:8000', changeOrigin: true } From 6b1af3b88195f9eba4cfb2fa0af27cbc4295fb1d Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Wed, 29 Apr 2026 10:34:12 -0500 Subject: [PATCH 3/6] cambios de vite config para apuntar a los archivos --- frontend/vite.config.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index c9ac8ce9..5603d80f 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -54,6 +54,10 @@ export default defineConfig({ '/api': { target: 'http://backend:8000', changeOrigin: true + }, + '/media': { + target: 'http://backend:8000', + changeOrigin: true } } }, From 85ecdc88fa156fcb68d3c091ace906222daeb824 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Wed, 6 May 2026 16:57:28 -0500 Subject: [PATCH 4/6] fix: estabilizar auth, proxy y traducciones del dashboard --- .../api/v1/modules/core/permissions/routes.py | 1 + backend/core/security.py | 9 +- backend/main.py | 2 +- backend_logs.txt | 290 ++++++++++++++++++ frontend/messages/en.json | 1 + frontend/messages/es.json | 1 + frontend/src/lib/api.ts | 1 + frontend/vite.config.ts | 2 +- 8 files changed, 303 insertions(+), 4 deletions(-) create mode 100644 backend_logs.txt diff --git a/backend/api/v1/modules/core/permissions/routes.py b/backend/api/v1/modules/core/permissions/routes.py index 31a55e21..7d38370c 100644 --- a/backend/api/v1/modules/core/permissions/routes.py +++ b/backend/api/v1/modules/core/permissions/routes.py @@ -78,6 +78,7 @@ async def get_my_permissions( """ # 1. Validar acceso básico a la compañía # Nota: pass None en required_permissions permite el paso al bootstrap + print(f"DEBUG: get_my_permissions: cia={company_id} user={current_user.get('preferred_username')}") tenant_id = validate_access_to_resource(db, company_id, current_user) user_id = current_user.get("sub") or current_user.get("id") diff --git a/backend/core/security.py b/backend/core/security.py index c2e12023..5d88da67 100644 --- a/backend/core/security.py +++ b/backend/core/security.py @@ -632,18 +632,21 @@ def validate_access_to_resource( """ tenant_id = resolve_effective_tenant_id_from_user(current_user) + print(f"DEBUG: validate_access_to_resource: tid={tenant_id} user={current_user.get('preferred_username')}") # Admin global Keycloak / master: lista ``roles`` del Hub (/auth/me), con fallback JWT. all_user_roles = collect_user_role_names(current_user) is_keycloak_admin = "admin" in all_user_roles + print(f"DEBUG: validate_access_to_resource: is_admin={is_keycloak_admin} roles={all_user_roles}") # 🚪 EXCEPCIÓN ESPECIAL: Si es el endpoint /me, permitimos el paso para el Bootstrap # Detectamos si no se requieren permisos (típico de /me) is_me_endpoint = required_permissions is None + print(f"DEBUG: validate_access_to_resource: is_me={is_me_endpoint} required={required_permissions}") if not is_keycloak_admin and not is_me_endpoint: if not validate_company_access(db, company_id, current_user): - print(f"DEBUG: Acceso denegado a compañía {company_id}") + print(f"DEBUG: validate_access_to_resource: ACCESO DENEGADO a cia {company_id}") raise HTTPException(status_code=403, detail="Access denied to this company") # Si no hay tenant_id, intentamos recuperarlo de la empresa @@ -693,7 +696,9 @@ def validate_access_to_resource( print(f"DEBUG: Error en auto-bootstrap de seguridad: {e}") if not has_access: - print(f"DEBUG: Permiso denegado. Faltan: {required_permissions}") + print(f"DEBUG: validate_access_to_resource: PERMISO DENEGADO. Faltan: {required_permissions}") raise HTTPException(status_code=403, detail="Permission denied") + + print(f"DEBUG: validate_access_to_resource: ACCESO CONCEDIDO") return tenant_id or 1 diff --git a/backend/main.py b/backend/main.py index 8af725a5..2fc08859 100644 --- a/backend/main.py +++ b/backend/main.py @@ -65,8 +65,8 @@ async def on_startup(): if settings.DEBUG: app.add_middleware(RequestLoggingMiddleware) -app.add_middleware(LicenseValidationMiddleware) app.add_middleware(TenantMiddleware) +app.add_middleware(LicenseValidationMiddleware) app.add_middleware(UserContextMiddleware) # CORS debe ser el último en añadirse para que sea el más externo diff --git a/backend_logs.txt b/backend_logs.txt new file mode 100644 index 00000000..04a08880 --- /dev/null +++ b/backend_logs.txt @@ -0,0 +1,290 @@ +anexo76-backend | Esperando a que PostgreSQL esté disponible en postgres-a76:5432... +anexo76-backend | ✓ PostgreSQL está listo y accesible +anexo76-backend | Iniciando proceso: uvicorn main:app --host 0.0.0.0 --port 8000 --reload --log-level info +anexo76-backend | INFO: Will watch for changes in these directories: ['/app'] +anexo76-backend | INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) +anexo76-backend | INFO: Started reloader process [1] using WatchFiles +anexo76-backend | DEBUG: Celery Broker URL: redis://valkey:6379/0 +anexo76-backend | INFO: Started server process [9] +anexo76-backend | INFO: Waiting for application startup. +anexo76-backend | 2026-05-06 21:36:55,160 - main - INFO - Iniciando la aplicación Anexo76... +anexo76-backend | INFO [alembic.runtime.migration] Context impl PostgresqlImpl. +anexo76-backend | INFO [alembic.runtime.migration] Will assume transactional DDL. +anexo76-backend | 2026-05-06 21:36:57,014 - botocore.hooks - DEBUG - Changing event name from creating-client-class.iot-data to creating-client-class.iot-data-plane +anexo76-backend | 2026-05-06 21:36:57,015 - botocore.hooks - DEBUG - Changing event name from before-call.apigateway to before-call.api-gateway +anexo76-backend | 2026-05-06 21:36:57,016 - botocore.hooks - DEBUG - Changing event name from request-created.machinelearning.Predict to request-created.machine-learning.Predict +anexo76-backend | 2026-05-06 21:36:57,016 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.autoscaling.CreateLaunchConfiguration to before-parameter-build.auto-scaling.CreateLaunchConfiguration +anexo76-backend | 2026-05-06 21:36:57,016 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.route53 to before-parameter-build.route-53 +anexo76-backend | 2026-05-06 21:36:57,016 - botocore.hooks - DEBUG - Changing event name from request-created.cloudsearchdomain.Search to request-created.cloudsearch-domain.Search +anexo76-backend | 2026-05-06 21:36:57,017 - botocore.hooks - DEBUG - Changing event name from docs.*.autoscaling.CreateLaunchConfiguration.complete-section to docs.*.auto-scaling.CreateLaunchConfiguration.complete-section +anexo76-backend | 2026-05-06 21:36:57,018 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.logs.CreateExportTask to before-parameter-build.cloudwatch-logs.CreateExportTask +anexo76-backend | 2026-05-06 21:36:57,018 - botocore.hooks - DEBUG - Changing event name from docs.*.logs.CreateExportTask.complete-section to docs.*.cloudwatch-logs.CreateExportTask.complete-section +anexo76-backend | 2026-05-06 21:36:57,018 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.cloudsearchdomain.Search to before-parameter-build.cloudsearch-domain.Search +anexo76-backend | 2026-05-06 21:36:57,018 - botocore.hooks - DEBUG - Changing event name from docs.*.cloudsearchdomain.Search.complete-section to docs.*.cloudsearch-domain.Search.complete-section +anexo76-backend | 2026-05-06 21:36:57,019 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/endpoints.json +anexo76-backend | 2026-05-06 21:36:57,029 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/sdk-default-configuration.json +anexo76-backend | 2026-05-06 21:36:57,030 - botocore.hooks - DEBUG - Event choose-service-name: calling handler +anexo76-backend | 2026-05-06 21:36:57,044 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/service-2.json.gz +anexo76-backend | 2026-05-06 21:36:57,049 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/service-2.sdk-extras.json +anexo76-backend | 2026-05-06 21:36:57,058 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/endpoint-rule-set-1.json.gz +anexo76-backend | 2026-05-06 21:36:57,060 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/partitions.json +anexo76-backend | 2026-05-06 21:36:57,062 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler +anexo76-backend | 2026-05-06 21:36:57,062 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler ._handler at 0x7da3be72fd80> +anexo76-backend | 2026-05-06 21:36:57,079 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler +anexo76-backend | 2026-05-06 21:36:57,080 - botocore.endpoint - DEBUG - Setting s3 timeout as (60, 60) +anexo76-backend | 2026-05-06 21:36:57,082 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/_retry.json +anexo76-backend | 2026-05-06 21:36:57,083 - botocore.client - DEBUG - Registering retry handlers for service: s3 +anexo76-backend | 2026-05-06 21:36:57,087 - botocore.utils - DEBUG - Registering S3 region redirector handler +anexo76-backend | 2026-05-06 21:36:57,087 - botocore.utils - DEBUG - Registering S3Express Identity Resolver +anexo76-backend | 2026-05-06 21:36:57,087 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,087 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,087 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:36:57,087 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:36:57,088 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,088 - botocore.hooks - DEBUG - Event before-endpoint-resolution.s3: calling handler +anexo76-backend | 2026-05-06 21:36:57,088 - botocore.hooks - DEBUG - Event before-endpoint-resolution.s3: calling handler > +anexo76-backend | 2026-05-06 21:36:57,088 - botocore.regions - DEBUG - Calling endpoint provider with parameters: {'Bucket': 'anexo76', 'Region': 'us-east-1', 'UseFIPS': False, 'UseDualStack': False, 'Endpoint': 'http://anexo76-minio:9000', 'ForcePathStyle': True, 'Accelerate': False, 'UseGlobalEndpoint': True, 'DisableMultiRegionAccessPoints': False, 'UseArnRegion': True} +anexo76-backend | 2026-05-06 21:36:57,088 - botocore.regions - DEBUG - Endpoint provider result: http://anexo76-minio:9000/anexo76 +anexo76-backend | 2026-05-06 21:36:57,088 - botocore.regions - DEBUG - Selecting from endpoint provider's list of auth schemes: "sigv4". User selected auth scheme is: "s3v4" +anexo76-backend | 2026-05-06 21:36:57,088 - botocore.regions - DEBUG - Selected auth type "v4" as "s3v4" with signing context params: {'region': 'us-east-1', 'signing_name': 's3', 'disableDoubleEncoding': True} +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.endpoint - DEBUG - Making request for OperationModel(name=HeadBucket) with params: {'url_path': '', 'query_string': {}, 'method': 'HEAD', 'headers': {'User-Agent': 'Boto3/1.35.36 md/Botocore#1.35.99 ua/2.0 os/linux#6.6.87.2-microsoft-standard-WSL2 md/arch#x86_64 lang/python#3.11.15 md/pyimpl#CPython cfg/retry-mode#legacy Botocore/1.35.99'}, 'body': b'', 'auth_path': '/anexo76/', 'url': 'http://anexo76-minio:9000/anexo76', 'context': {'client_region': 'us-east-1', 'client_config': , 'has_streaming_input': False, 'auth_type': 's3v4', 'unsigned_payload': None, 's3_redirect': {'redirected': False, 'bucket': 'anexo76', 'params': {'Bucket': 'anexo76'}}, 'input_params': {'Bucket': 'anexo76'}, 'signing': {'region': 'us-east-1', 'signing_name': 's3', 'disableDoubleEncoding': True}, 'endpoint_properties': {'authSchemes': [{'disableDoubleEncoding': True, 'name': 'sigv4', 'signingName': 's3', 'signingRegion': 'us-east-1'}]}}} +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event request-created.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event choose-signer.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-sign.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-sign.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.auth - DEBUG - Calculating signature using v4 auth. +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.auth - DEBUG - CanonicalRequest: +anexo76-backend | HEAD +anexo76-backend | /anexo76 +anexo76-backend | +anexo76-backend | host:anexo76-minio:9000 +anexo76-backend | x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +anexo76-backend | x-amz-date:20260506T213657Z +anexo76-backend | +anexo76-backend | host;x-amz-content-sha256;x-amz-date +anexo76-backend | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.auth - DEBUG - StringToSign: +anexo76-backend | AWS4-HMAC-SHA256 +anexo76-backend | 20260506T213657Z +anexo76-backend | 20260506/us-east-1/s3/aws4_request +anexo76-backend | 78f951a26193833ad927530efec5410bb55c4a7f8201543949aeeea0681e2809 +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.auth - DEBUG - Signature: +anexo76-backend | d6d66e8b6373a1ce555bba3571cf99e4819f2ca5d56772a4dde668a36d0c5b13 +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event request-created.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,089 - botocore.endpoint - DEBUG - Sending http request: +anexo76-backend | 2026-05-06 21:36:57,090 - urllib3.connectionpool - DEBUG - Starting new HTTP connection (1): anexo76-minio:9000 +anexo76-backend | 2026-05-06 21:36:57,092 - urllib3.connectionpool - DEBUG - http://anexo76-minio:9000 "HEAD /anexo76 HTTP/1.1" 200 0 +anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event before-parse.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event before-parse.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,093 - botocore.parsers - DEBUG - Response headers: {'Accept-Ranges': 'bytes', 'Content-Length': '0', 'Content-Type': 'application/xml', 'Server': 'MinIO', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains', 'Vary': 'Origin, Accept-Encoding', 'X-Amz-Id-2': 'dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8', 'X-Amz-Request-Id': '18AD17A315A8843E', 'X-Content-Type-Options': 'nosniff', 'X-Ratelimit-Limit': '3115', 'X-Ratelimit-Remaining': '3115', 'X-Xss-Protection': '1; mode=block', 'Date': 'Wed, 06 May 2026 21:36:57 GMT'} +anexo76-backend | 2026-05-06 21:36:57,093 - botocore.parsers - DEBUG - Response body: +anexo76-backend | b'' +anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:36:57,093 - botocore.retryhandler - DEBUG - No retry needed. +anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:36:57,093 - core.storage_s3 - INFO - S3 bucket anexo76 exists +anexo76-backend | 2026-05-06 21:36:57,094 - main - INFO - Base de datos inicializada correctamente. +anexo76-backend | INFO: Application startup complete. +anexo76-backend | INFO: 127.0.0.1:33668 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 172.21.0.3:57858 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:33954 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | 2026-05-06 21:37:31,535 - httpcore.connection - DEBUG - connect_tcp.started host='workspace.aduanasoft.com' port=443 local_address=None timeout=5.0 socket_options=None +anexo76-backend | 2026-05-06 21:37:31,566 - httpcore.connection - DEBUG - connect_tcp.complete return_value= +anexo76-backend | 2026-05-06 21:37:31,566 - httpcore.connection - DEBUG - start_tls.started ssl_context= server_hostname='workspace.aduanasoft.com' timeout=5.0 +anexo76-backend | 2026-05-06 21:37:31,597 - httpcore.connection - DEBUG - start_tls.complete return_value= +anexo76-backend | 2026-05-06 21:37:31,597 - httpcore.http11 - DEBUG - send_request_headers.started request= +anexo76-backend | 2026-05-06 21:37:31,598 - httpcore.http11 - DEBUG - send_request_headers.complete +anexo76-backend | 2026-05-06 21:37:31,598 - httpcore.http11 - DEBUG - send_request_body.started request= +anexo76-backend | 2026-05-06 21:37:31,598 - httpcore.http11 - DEBUG - send_request_body.complete +anexo76-backend | 2026-05-06 21:37:31,598 - httpcore.http11 - DEBUG - receive_response_headers.started request= +anexo76-backend | 2026-05-06 21:37:31,662 - httpcore.http11 - DEBUG - receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Server', b'nginx/1.22.1'), (b'Date', b'Wed, 06 May 2026 21:37:34 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'250'), (b'Connection', b'keep-alive'), (b'x-request-id', b'296211c5-34bd-4c02-9cfb-176e09897234')]) +anexo76-backend | 2026-05-06 21:37:31,663 - httpx - INFO - HTTP Request: GET https://workspace.aduanasoft.com/api/v1/auth/me "HTTP/1.1 200 OK" +anexo76-backend | 2026-05-06 21:37:31,663 - httpcore.http11 - DEBUG - receive_response_body.started request= +anexo76-backend | 2026-05-06 21:37:31,663 - httpcore.http11 - DEBUG - receive_response_body.complete +anexo76-backend | 2026-05-06 21:37:31,664 - httpcore.http11 - DEBUG - response_closed.started +anexo76-backend | 2026-05-06 21:37:31,664 - httpcore.http11 - DEBUG - response_closed.complete +anexo76-backend | 2026-05-06 21:37:31,664 - httpcore.connection - DEBUG - close.started +anexo76-backend | 2026-05-06 21:37:31,664 - httpcore.connection - DEBUG - close.complete +anexo76-backend | 2026-05-06 21:37:31,665 - core.middleware - INFO - [license] tenant override propagated to Hub: 11 +anexo76-backend | 2026-05-06 21:37:31,670 - httpcore.connection - DEBUG - connect_tcp.started host='workspace.aduanasoft.com' port=443 local_address=None timeout=5.0 socket_options=None +anexo76-backend | 2026-05-06 21:37:31,700 - httpcore.connection - DEBUG - connect_tcp.complete return_value= +anexo76-backend | 2026-05-06 21:37:31,700 - httpcore.connection - DEBUG - start_tls.started ssl_context= server_hostname='workspace.aduanasoft.com' timeout=5.0 +anexo76-backend | 2026-05-06 21:37:31,730 - httpcore.connection - DEBUG - start_tls.complete return_value= +anexo76-backend | 2026-05-06 21:37:31,730 - httpcore.http11 - DEBUG - send_request_headers.started request= +anexo76-backend | 2026-05-06 21:37:31,731 - httpcore.http11 - DEBUG - send_request_headers.complete +anexo76-backend | 2026-05-06 21:37:31,731 - httpcore.http11 - DEBUG - send_request_body.started request= +anexo76-backend | 2026-05-06 21:37:31,731 - httpcore.http11 - DEBUG - send_request_body.complete +anexo76-backend | 2026-05-06 21:37:31,731 - httpcore.http11 - DEBUG - receive_response_headers.started request= +anexo76-backend | 2026-05-06 21:37:31,824 - httpcore.http11 - DEBUG - receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Server', b'nginx/1.22.1'), (b'Date', b'Wed, 06 May 2026 21:37:35 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'224'), (b'Connection', b'keep-alive'), (b'x-request-id', b'f4bfac19-d54b-4216-bbd4-011f9ff783e8')]) +anexo76-backend | 2026-05-06 21:37:31,825 - httpx - INFO - HTTP Request: GET https://workspace.aduanasoft.com/api/v1/auth/verify-license "HTTP/1.1 200 OK" +anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.http11 - DEBUG - receive_response_body.started request= +anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.http11 - DEBUG - receive_response_body.complete +anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.http11 - DEBUG - response_closed.started +anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.http11 - DEBUG - response_closed.complete +anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.connection - DEBUG - close.started +anexo76-backend | 2026-05-06 21:37:31,826 - httpcore.connection - DEBUG - close.complete +anexo76-backend | 2026-05-06 21:37:31,826 - core.middleware - INFO - 🔑 verify-license → status=200 body={"valid":true,"message":"Licencia activa y válida","tenant_slug":"aduanasoft","tenant_name":"aduanasoft","product_name":null,"expires_at":"2027-04-29T17:32:31.670550","plan":"basic","max_users":20,"features":["api_access"]} +anexo76-backend | 2026-05-06 21:37:31,826 - core.middleware - INFO - Request: GET /api/v1/a76/company/my-companies +anexo76-backend | 2026-05-06 21:37:31,836 - core.security - INFO - [get_current_user] X-Tenant-Override='11' +anexo76-backend | 2026-05-06 21:37:31,843 - httpcore.connection - DEBUG - connect_tcp.started host='workspace.aduanasoft.com' port=443 local_address=None timeout=5.0 socket_options=None +anexo76-backend | 2026-05-06 21:37:31,872 - httpcore.connection - DEBUG - connect_tcp.complete return_value= +anexo76-backend | 2026-05-06 21:37:31,873 - httpcore.connection - DEBUG - start_tls.started ssl_context= server_hostname='workspace.aduanasoft.com' timeout=5.0 +anexo76-backend | 2026-05-06 21:37:31,902 - httpcore.connection - DEBUG - start_tls.complete return_value= +anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - send_request_headers.started request= +anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - send_request_headers.complete +anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - send_request_body.started request= +anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - send_request_body.complete +anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - receive_response_headers.started request= +anexo76-backend | 2026-05-06 21:37:31,983 - httpcore.http11 - DEBUG - receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Server', b'nginx/1.22.1'), (b'Date', b'Wed, 06 May 2026 21:37:35 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'250'), (b'Connection', b'keep-alive'), (b'x-request-id', b'9f3faac1-6e02-4160-87b4-22af7df1ef11')]) +anexo76-backend | 2026-05-06 21:37:31,984 - httpx - INFO - HTTP Request: GET https://workspace.aduanasoft.com/api/v1/auth/me "HTTP/1.1 200 OK" +anexo76-backend | 2026-05-06 21:37:31,984 - httpcore.http11 - DEBUG - receive_response_body.started request= +anexo76-backend | 2026-05-06 21:37:31,984 - httpcore.http11 - DEBUG - receive_response_body.complete +anexo76-backend | 2026-05-06 21:37:31,984 - httpcore.http11 - DEBUG - response_closed.started +anexo76-backend | 2026-05-06 21:37:31,984 - httpcore.http11 - DEBUG - response_closed.complete +anexo76-backend | 2026-05-06 21:37:31,985 - httpcore.connection - DEBUG - close.started +anexo76-backend | 2026-05-06 21:37:31,985 - httpcore.connection - DEBUG - close.complete +anexo76-backend | 2026-05-06 21:37:32,585 - core.middleware - INFO - Response: GET /api/v1/a76/company/my-companies Status: 200 Duration: 0.759s +anexo76-backend | INFO: 172.21.0.3:45462 - "GET /api/v1/a76/company/my-companies HTTP/1.1" 200 OK +anexo76-backend | 2026-05-06 21:37:32,590 - core.middleware - INFO - Request: GET /api/v1/auth/me +anexo76-backend | 2026-05-06 21:37:32,591 - core.middleware - INFO - Response: GET /api/v1/auth/me Status: 200 Duration: 0.001s +anexo76-backend | INFO: 172.21.0.3:45470 - "GET /api/v1/auth/me HTTP/1.1" 200 OK +anexo76-backend | 2026-05-06 21:37:32,595 - core.middleware - INFO - [license] tenant override propagated to Hub: 11 +anexo76-backend | 2026-05-06 21:37:32,601 - httpcore.connection - DEBUG - connect_tcp.started host='workspace.aduanasoft.com' port=443 local_address=None timeout=5.0 socket_options=None +anexo76-backend | 2026-05-06 21:37:32,631 - httpcore.connection - DEBUG - connect_tcp.complete return_value= +anexo76-backend | 2026-05-06 21:37:32,631 - httpcore.connection - DEBUG - start_tls.started ssl_context= server_hostname='workspace.aduanasoft.com' timeout=5.0 +anexo76-backend | 2026-05-06 21:37:32,661 - httpcore.connection - DEBUG - start_tls.complete return_value= +anexo76-backend | 2026-05-06 21:37:32,662 - httpcore.http11 - DEBUG - send_request_headers.started request= +anexo76-backend | 2026-05-06 21:37:32,662 - httpcore.http11 - DEBUG - send_request_headers.complete +anexo76-backend | 2026-05-06 21:37:32,662 - httpcore.http11 - DEBUG - send_request_body.started request= +anexo76-backend | 2026-05-06 21:37:32,663 - httpcore.http11 - DEBUG - send_request_body.complete +anexo76-backend | 2026-05-06 21:37:32,663 - httpcore.http11 - DEBUG - receive_response_headers.started request= +anexo76-backend | 2026-05-06 21:37:32,756 - httpcore.http11 - DEBUG - receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Server', b'nginx/1.22.1'), (b'Date', b'Wed, 06 May 2026 21:37:36 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'224'), (b'Connection', b'keep-alive'), (b'x-request-id', b'b99812fe-d833-46f2-9008-b3fd669d9972')]) +anexo76-backend | 2026-05-06 21:37:32,757 - httpx - INFO - HTTP Request: GET https://workspace.aduanasoft.com/api/v1/auth/verify-license "HTTP/1.1 200 OK" +anexo76-backend | 2026-05-06 21:37:32,757 - httpcore.http11 - DEBUG - receive_response_body.started request= +anexo76-backend | 2026-05-06 21:37:32,757 - httpcore.http11 - DEBUG - receive_response_body.complete +anexo76-backend | 2026-05-06 21:37:32,757 - httpcore.http11 - DEBUG - response_closed.started +anexo76-backend | 2026-05-06 21:37:32,757 - httpcore.http11 - DEBUG - response_closed.complete +anexo76-backend | 2026-05-06 21:37:32,758 - httpcore.connection - DEBUG - close.started +anexo76-backend | 2026-05-06 21:37:32,758 - httpcore.connection - DEBUG - close.complete +anexo76-backend | 2026-05-06 21:37:32,758 - core.middleware - INFO - 🔑 verify-license → status=200 body={"valid":true,"message":"Licencia activa y válida","tenant_slug":"aduanasoft","tenant_name":"aduanasoft","product_name":null,"expires_at":"2027-04-29T17:32:31.670550","plan":"basic","max_users":20,"features":["api_access"]} +anexo76-backend | 2026-05-06 21:37:32,758 - core.middleware - INFO - Request: GET /api/v1/core/users/me/profile +anexo76-backend | 2026-05-06 21:37:32,759 - core.security - INFO - [get_current_user] X-Tenant-Override='11' +anexo76-backend | 2026-05-06 21:37:32,770 - core.middleware - INFO - Response: GET /api/v1/core/users/me/profile Status: 200 Duration: 0.011s +anexo76-backend | INFO: 172.21.0.3:45462 - "GET /api/v1/core/users/me/profile HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:35456 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | 2026-05-06 21:37:47,554 - core.middleware - INFO - Request: GET /api/avatars/default.jpg +anexo76-backend | 2026-05-06 21:37:47,558 - core.middleware - INFO - Response: GET /api/avatars/default.jpg Status: 404 Duration: 0.004s +anexo76-backend | INFO: 172.21.0.3:53544 - "GET /api/avatars/default.jpg HTTP/1.1" 404 Not Found +anexo76-backend | INFO: 172.21.0.3:53560 - "POST /api-sveltekit/auth/silent-refresh HTTP/1.1" 401 Unauthorized +anexo76-backend | INFO: 172.21.0.3:53566 - "POST /api-sveltekit/company/set-active HTTP/1.1" 401 Unauthorized +anexo76-backend | 2026-05-06 21:37:49,296 - core.middleware - INFO - Request: GET /api/avatars/default.jpg +anexo76-backend | 2026-05-06 21:37:49,298 - core.middleware - INFO - Response: GET /api/avatars/default.jpg Status: 404 Duration: 0.002s +anexo76-backend | INFO: 172.21.0.3:53576 - "GET /api/avatars/default.jpg HTTP/1.1" 404 Not Found +anexo76-backend | INFO: 127.0.0.1:37842 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:60858 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:47212 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:38264 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:45138 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:54772 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:39924 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | WARNING: WatchFiles detected changes in 'api/v1/modules/core/permissions/routes.py'. Reloading... +anexo76-backend | INFO: Shutting down +anexo76-backend | INFO: Waiting for application shutdown. +anexo76-backend | INFO: Application shutdown complete. +anexo76-backend | INFO: Finished server process [9] +anexo76-backend | DEBUG: Celery Broker URL: redis://valkey:6379/0 +anexo76-backend | INFO: Started server process [94] +anexo76-backend | INFO: Waiting for application startup. +anexo76-backend | 2026-05-06 21:40:24,734 - main - INFO - Iniciando la aplicación Anexo76... +anexo76-backend | INFO [alembic.runtime.migration] Context impl PostgresqlImpl. +anexo76-backend | INFO [alembic.runtime.migration] Will assume transactional DDL. +anexo76-backend | 2026-05-06 21:40:26,311 - botocore.hooks - DEBUG - Changing event name from creating-client-class.iot-data to creating-client-class.iot-data-plane +anexo76-backend | 2026-05-06 21:40:26,312 - botocore.hooks - DEBUG - Changing event name from before-call.apigateway to before-call.api-gateway +anexo76-backend | 2026-05-06 21:40:26,313 - botocore.hooks - DEBUG - Changing event name from request-created.machinelearning.Predict to request-created.machine-learning.Predict +anexo76-backend | 2026-05-06 21:40:26,313 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.autoscaling.CreateLaunchConfiguration to before-parameter-build.auto-scaling.CreateLaunchConfiguration +anexo76-backend | 2026-05-06 21:40:26,313 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.route53 to before-parameter-build.route-53 +anexo76-backend | 2026-05-06 21:40:26,313 - botocore.hooks - DEBUG - Changing event name from request-created.cloudsearchdomain.Search to request-created.cloudsearch-domain.Search +anexo76-backend | 2026-05-06 21:40:26,314 - botocore.hooks - DEBUG - Changing event name from docs.*.autoscaling.CreateLaunchConfiguration.complete-section to docs.*.auto-scaling.CreateLaunchConfiguration.complete-section +anexo76-backend | 2026-05-06 21:40:26,315 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.logs.CreateExportTask to before-parameter-build.cloudwatch-logs.CreateExportTask +anexo76-backend | 2026-05-06 21:40:26,315 - botocore.hooks - DEBUG - Changing event name from docs.*.logs.CreateExportTask.complete-section to docs.*.cloudwatch-logs.CreateExportTask.complete-section +anexo76-backend | 2026-05-06 21:40:26,315 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.cloudsearchdomain.Search to before-parameter-build.cloudsearch-domain.Search +anexo76-backend | 2026-05-06 21:40:26,315 - botocore.hooks - DEBUG - Changing event name from docs.*.cloudsearchdomain.Search.complete-section to docs.*.cloudsearch-domain.Search.complete-section +anexo76-backend | 2026-05-06 21:40:26,320 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/endpoints.json +anexo76-backend | 2026-05-06 21:40:26,331 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/sdk-default-configuration.json +anexo76-backend | 2026-05-06 21:40:26,331 - botocore.hooks - DEBUG - Event choose-service-name: calling handler +anexo76-backend | 2026-05-06 21:40:26,364 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/service-2.json.gz +anexo76-backend | 2026-05-06 21:40:26,386 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/service-2.sdk-extras.json +anexo76-backend | 2026-05-06 21:40:26,395 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/endpoint-rule-set-1.json.gz +anexo76-backend | 2026-05-06 21:40:26,415 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/partitions.json +anexo76-backend | 2026-05-06 21:40:26,416 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler +anexo76-backend | 2026-05-06 21:40:26,417 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler ._handler at 0x7e12d5327e20> +anexo76-backend | 2026-05-06 21:40:26,450 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler +anexo76-backend | 2026-05-06 21:40:26,451 - botocore.endpoint - DEBUG - Setting s3 timeout as (60, 60) +anexo76-backend | 2026-05-06 21:40:26,455 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/_retry.json +anexo76-backend | 2026-05-06 21:40:26,455 - botocore.client - DEBUG - Registering retry handlers for service: s3 +anexo76-backend | 2026-05-06 21:40:26,455 - botocore.utils - DEBUG - Registering S3 region redirector handler +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.utils - DEBUG - Registering S3Express Identity Resolver +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-endpoint-resolution.s3: calling handler +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-endpoint-resolution.s3: calling handler > +anexo76-backend | 2026-05-06 21:40:26,456 - botocore.regions - DEBUG - Calling endpoint provider with parameters: {'Bucket': 'anexo76', 'Region': 'us-east-1', 'UseFIPS': False, 'UseDualStack': False, 'Endpoint': 'http://anexo76-minio:9000', 'ForcePathStyle': True, 'Accelerate': False, 'UseGlobalEndpoint': True, 'DisableMultiRegionAccessPoints': False, 'UseArnRegion': True} +anexo76-backend | 2026-05-06 21:40:26,457 - botocore.regions - DEBUG - Endpoint provider result: http://anexo76-minio:9000/anexo76 +anexo76-backend | 2026-05-06 21:40:26,457 - botocore.regions - DEBUG - Selecting from endpoint provider's list of auth schemes: "sigv4". User selected auth scheme is: "s3v4" +anexo76-backend | 2026-05-06 21:40:26,457 - botocore.regions - DEBUG - Selected auth type "v4" as "s3v4" with signing context params: {'region': 'us-east-1', 'signing_name': 's3', 'disableDoubleEncoding': True} +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.endpoint - DEBUG - Making request for OperationModel(name=HeadBucket) with params: {'url_path': '', 'query_string': {}, 'method': 'HEAD', 'headers': {'User-Agent': 'Boto3/1.35.36 md/Botocore#1.35.99 ua/2.0 os/linux#6.6.87.2-microsoft-standard-WSL2 md/arch#x86_64 lang/python#3.11.15 md/pyimpl#CPython cfg/retry-mode#legacy Botocore/1.35.99'}, 'body': b'', 'auth_path': '/anexo76/', 'url': 'http://anexo76-minio:9000/anexo76', 'context': {'client_region': 'us-east-1', 'client_config': , 'has_streaming_input': False, 'auth_type': 's3v4', 'unsigned_payload': None, 's3_redirect': {'redirected': False, 'bucket': 'anexo76', 'params': {'Bucket': 'anexo76'}}, 'input_params': {'Bucket': 'anexo76'}, 'signing': {'region': 'us-east-1', 'signing_name': 's3', 'disableDoubleEncoding': True}, 'endpoint_properties': {'authSchemes': [{'disableDoubleEncoding': True, 'name': 'sigv4', 'signingName': 's3', 'signingRegion': 'us-east-1'}]}}} +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event request-created.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event choose-signer.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-sign.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-sign.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:40:26,459 - botocore.auth - DEBUG - Calculating signature using v4 auth. +anexo76-backend | 2026-05-06 21:40:26,459 - botocore.auth - DEBUG - CanonicalRequest: +anexo76-backend | HEAD +anexo76-backend | /anexo76 +anexo76-backend | +anexo76-backend | host:anexo76-minio:9000 +anexo76-backend | x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +anexo76-backend | x-amz-date:20260506T214026Z +anexo76-backend | +anexo76-backend | host;x-amz-content-sha256;x-amz-date +anexo76-backend | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +anexo76-backend | 2026-05-06 21:40:26,459 - botocore.auth - DEBUG - StringToSign: +anexo76-backend | AWS4-HMAC-SHA256 +anexo76-backend | 20260506T214026Z +anexo76-backend | 20260506/us-east-1/s3/aws4_request +anexo76-backend | 9c598ef422ed5a1f958ce1e61ea627a1c47025c80840ef18d19d1417b9d5c0b8 +anexo76-backend | 2026-05-06 21:40:26,459 - botocore.auth - DEBUG - Signature: +anexo76-backend | 4b5dcb6959901de692d7e3377b48be53bbf6665daf7be709a25af49ee8561df3 +anexo76-backend | 2026-05-06 21:40:26,459 - botocore.hooks - DEBUG - Event request-created.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,459 - botocore.endpoint - DEBUG - Sending http request: +anexo76-backend | 2026-05-06 21:40:26,461 - urllib3.connectionpool - DEBUG - Starting new HTTP connection (1): anexo76-minio:9000 +anexo76-backend | 2026-05-06 21:40:26,463 - urllib3.connectionpool - DEBUG - http://anexo76-minio:9000 "HEAD /anexo76 HTTP/1.1" 200 0 +anexo76-backend | 2026-05-06 21:40:26,463 - botocore.hooks - DEBUG - Event before-parse.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,463 - botocore.hooks - DEBUG - Event before-parse.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,463 - botocore.parsers - DEBUG - Response headers: {'Accept-Ranges': 'bytes', 'Content-Length': '0', 'Content-Type': 'application/xml', 'Server': 'MinIO', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains', 'Vary': 'Origin, Accept-Encoding', 'X-Amz-Id-2': 'dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8', 'X-Amz-Request-Id': '18AD17D3D5264B2C', 'X-Content-Type-Options': 'nosniff', 'X-Ratelimit-Limit': '3115', 'X-Ratelimit-Remaining': '3115', 'X-Xss-Protection': '1; mode=block', 'Date': 'Wed, 06 May 2026 21:40:26 GMT'} +anexo76-backend | 2026-05-06 21:40:26,463 - botocore.parsers - DEBUG - Response body: +anexo76-backend | b'' +anexo76-backend | 2026-05-06 21:40:26,464 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,464 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler +anexo76-backend | 2026-05-06 21:40:26,464 - botocore.retryhandler - DEBUG - No retry needed. +anexo76-backend | 2026-05-06 21:40:26,464 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler > +anexo76-backend | 2026-05-06 21:40:26,464 - core.storage_s3 - INFO - S3 bucket anexo76 exists +anexo76-backend | 2026-05-06 21:40:26,464 - main - INFO - Base de datos inicializada correctamente. +anexo76-backend | INFO: Application startup complete. +anexo76-backend | INFO: 127.0.0.1:49166 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:39678 - "GET /api/health HTTP/1.1" 200 OK +anexo76-backend | INFO: 127.0.0.1:59246 - "GET /api/health HTTP/1.1" 200 OK diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 730bd4d6..5dd317c5 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -1,6 +1,7 @@ { "$schema": "https://inlang.com/schema/inlang-message-format", "hello_world": "Hello, {name} from en!", + "exchange_rate_error_title": "Exchange Rate Error", "dashboard": { "greeting_morning": "Good morning", "greeting_afternoon": "Good afternoon", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index d8c653db..b6bbd48e 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -1,6 +1,7 @@ { "$schema": "https://inlang.com/schema/inlang-message-format", "hello_world": "Hello, {name} from es!", + "exchange_rate_error_title": "Error de Tipo de Cambio", "dashboard": { "greeting_morning": "Buenos días", "greeting_afternoon": "Buenas tardes", diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index cd036ea2..cda4698a 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -16,6 +16,7 @@ function normalizeAbsoluteApiBaseUrl(raw: string): string { if (s.startsWith('https:') && !s.startsWith('https://')) { s = 'https://' + s.slice('https:'.length).replace(/^\/+/, ''); } + if (s.startsWith('/')) return s; if (/^https?:\/\//i.test(s)) return s; return `http://${s.replace(/^\/+/, '')}`; } diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 5603d80f..c2a032c1 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -51,7 +51,7 @@ export default defineConfig({ // 'otro-host.com' si necesitas más ], proxy: { - '/api': { + '/api/': { target: 'http://backend:8000', changeOrigin: true }, From beaf9b2f8eeccf612c4e7747268249872a431591 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 7 May 2026 11:41:44 -0500 Subject: [PATCH 5/6] Correcion con vite, borrar los print y mejorar la barra de manuales --- .../api/v1/modules/core/permissions/routes.py | 1 - backend/core/security.py | 13 +- backend_logs.txt | 290 ------------------ .../src/lib/components/help/HelpDrawer.svelte | 28 +- frontend/vite.config.ts | 4 +- 5 files changed, 32 insertions(+), 304 deletions(-) delete mode 100644 backend_logs.txt diff --git a/backend/api/v1/modules/core/permissions/routes.py b/backend/api/v1/modules/core/permissions/routes.py index 7d38370c..31a55e21 100644 --- a/backend/api/v1/modules/core/permissions/routes.py +++ b/backend/api/v1/modules/core/permissions/routes.py @@ -78,7 +78,6 @@ async def get_my_permissions( """ # 1. Validar acceso básico a la compañía # Nota: pass None en required_permissions permite el paso al bootstrap - print(f"DEBUG: get_my_permissions: cia={company_id} user={current_user.get('preferred_username')}") tenant_id = validate_access_to_resource(db, company_id, current_user) user_id = current_user.get("sub") or current_user.get("id") diff --git a/backend/core/security.py b/backend/core/security.py index 5d88da67..bfdac99c 100644 --- a/backend/core/security.py +++ b/backend/core/security.py @@ -600,6 +600,10 @@ def validate_company_access( .first() ) + if not company: + print(f"DEBUG: validate_company_access: No se encontró la compañía {company_id} para el tenant {tenant_id}") + logger.warning(f"validate_company_access: No se encontró la compañía {company_id} para el tenant {tenant_id}") + return company is not None except Exception as e: logger.error("Error validating company access: %s", e) @@ -632,21 +636,18 @@ def validate_access_to_resource( """ tenant_id = resolve_effective_tenant_id_from_user(current_user) - print(f"DEBUG: validate_access_to_resource: tid={tenant_id} user={current_user.get('preferred_username')}") # Admin global Keycloak / master: lista ``roles`` del Hub (/auth/me), con fallback JWT. all_user_roles = collect_user_role_names(current_user) is_keycloak_admin = "admin" in all_user_roles - print(f"DEBUG: validate_access_to_resource: is_admin={is_keycloak_admin} roles={all_user_roles}") # 🚪 EXCEPCIÓN ESPECIAL: Si es el endpoint /me, permitimos el paso para el Bootstrap # Detectamos si no se requieren permisos (típico de /me) is_me_endpoint = required_permissions is None - print(f"DEBUG: validate_access_to_resource: is_me={is_me_endpoint} required={required_permissions}") if not is_keycloak_admin and not is_me_endpoint: if not validate_company_access(db, company_id, current_user): - print(f"DEBUG: validate_access_to_resource: ACCESO DENEGADO a cia {company_id}") + print(f"DEBUG: Acceso denegado a compañía {company_id}") raise HTTPException(status_code=403, detail="Access denied to this company") # Si no hay tenant_id, intentamos recuperarlo de la empresa @@ -696,9 +697,7 @@ def validate_access_to_resource( print(f"DEBUG: Error en auto-bootstrap de seguridad: {e}") if not has_access: - print(f"DEBUG: validate_access_to_resource: PERMISO DENEGADO. Faltan: {required_permissions}") + print(f"DEBUG: Permiso denegado. Faltan: {required_permissions}") raise HTTPException(status_code=403, detail="Permission denied") - - print(f"DEBUG: validate_access_to_resource: ACCESO CONCEDIDO") return tenant_id or 1 diff --git a/backend_logs.txt b/backend_logs.txt deleted file mode 100644 index 04a08880..00000000 --- a/backend_logs.txt +++ /dev/null @@ -1,290 +0,0 @@ -anexo76-backend | Esperando a que PostgreSQL esté disponible en postgres-a76:5432... -anexo76-backend | ✓ PostgreSQL está listo y accesible -anexo76-backend | Iniciando proceso: uvicorn main:app --host 0.0.0.0 --port 8000 --reload --log-level info -anexo76-backend | INFO: Will watch for changes in these directories: ['/app'] -anexo76-backend | INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) -anexo76-backend | INFO: Started reloader process [1] using WatchFiles -anexo76-backend | DEBUG: Celery Broker URL: redis://valkey:6379/0 -anexo76-backend | INFO: Started server process [9] -anexo76-backend | INFO: Waiting for application startup. -anexo76-backend | 2026-05-06 21:36:55,160 - main - INFO - Iniciando la aplicación Anexo76... -anexo76-backend | INFO [alembic.runtime.migration] Context impl PostgresqlImpl. -anexo76-backend | INFO [alembic.runtime.migration] Will assume transactional DDL. -anexo76-backend | 2026-05-06 21:36:57,014 - botocore.hooks - DEBUG - Changing event name from creating-client-class.iot-data to creating-client-class.iot-data-plane -anexo76-backend | 2026-05-06 21:36:57,015 - botocore.hooks - DEBUG - Changing event name from before-call.apigateway to before-call.api-gateway -anexo76-backend | 2026-05-06 21:36:57,016 - botocore.hooks - DEBUG - Changing event name from request-created.machinelearning.Predict to request-created.machine-learning.Predict -anexo76-backend | 2026-05-06 21:36:57,016 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.autoscaling.CreateLaunchConfiguration to before-parameter-build.auto-scaling.CreateLaunchConfiguration -anexo76-backend | 2026-05-06 21:36:57,016 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.route53 to before-parameter-build.route-53 -anexo76-backend | 2026-05-06 21:36:57,016 - botocore.hooks - DEBUG - Changing event name from request-created.cloudsearchdomain.Search to request-created.cloudsearch-domain.Search -anexo76-backend | 2026-05-06 21:36:57,017 - botocore.hooks - DEBUG - Changing event name from docs.*.autoscaling.CreateLaunchConfiguration.complete-section to docs.*.auto-scaling.CreateLaunchConfiguration.complete-section -anexo76-backend | 2026-05-06 21:36:57,018 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.logs.CreateExportTask to before-parameter-build.cloudwatch-logs.CreateExportTask -anexo76-backend | 2026-05-06 21:36:57,018 - botocore.hooks - DEBUG - Changing event name from docs.*.logs.CreateExportTask.complete-section to docs.*.cloudwatch-logs.CreateExportTask.complete-section -anexo76-backend | 2026-05-06 21:36:57,018 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.cloudsearchdomain.Search to before-parameter-build.cloudsearch-domain.Search -anexo76-backend | 2026-05-06 21:36:57,018 - botocore.hooks - DEBUG - Changing event name from docs.*.cloudsearchdomain.Search.complete-section to docs.*.cloudsearch-domain.Search.complete-section -anexo76-backend | 2026-05-06 21:36:57,019 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/endpoints.json -anexo76-backend | 2026-05-06 21:36:57,029 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/sdk-default-configuration.json -anexo76-backend | 2026-05-06 21:36:57,030 - botocore.hooks - DEBUG - Event choose-service-name: calling handler -anexo76-backend | 2026-05-06 21:36:57,044 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/service-2.json.gz -anexo76-backend | 2026-05-06 21:36:57,049 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/service-2.sdk-extras.json -anexo76-backend | 2026-05-06 21:36:57,058 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/endpoint-rule-set-1.json.gz -anexo76-backend | 2026-05-06 21:36:57,060 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/partitions.json -anexo76-backend | 2026-05-06 21:36:57,062 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler -anexo76-backend | 2026-05-06 21:36:57,062 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler ._handler at 0x7da3be72fd80> -anexo76-backend | 2026-05-06 21:36:57,079 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler -anexo76-backend | 2026-05-06 21:36:57,080 - botocore.endpoint - DEBUG - Setting s3 timeout as (60, 60) -anexo76-backend | 2026-05-06 21:36:57,082 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/_retry.json -anexo76-backend | 2026-05-06 21:36:57,083 - botocore.client - DEBUG - Registering retry handlers for service: s3 -anexo76-backend | 2026-05-06 21:36:57,087 - botocore.utils - DEBUG - Registering S3 region redirector handler -anexo76-backend | 2026-05-06 21:36:57,087 - botocore.utils - DEBUG - Registering S3Express Identity Resolver -anexo76-backend | 2026-05-06 21:36:57,087 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,087 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,087 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:36:57,087 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:36:57,088 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,088 - botocore.hooks - DEBUG - Event before-endpoint-resolution.s3: calling handler -anexo76-backend | 2026-05-06 21:36:57,088 - botocore.hooks - DEBUG - Event before-endpoint-resolution.s3: calling handler > -anexo76-backend | 2026-05-06 21:36:57,088 - botocore.regions - DEBUG - Calling endpoint provider with parameters: {'Bucket': 'anexo76', 'Region': 'us-east-1', 'UseFIPS': False, 'UseDualStack': False, 'Endpoint': 'http://anexo76-minio:9000', 'ForcePathStyle': True, 'Accelerate': False, 'UseGlobalEndpoint': True, 'DisableMultiRegionAccessPoints': False, 'UseArnRegion': True} -anexo76-backend | 2026-05-06 21:36:57,088 - botocore.regions - DEBUG - Endpoint provider result: http://anexo76-minio:9000/anexo76 -anexo76-backend | 2026-05-06 21:36:57,088 - botocore.regions - DEBUG - Selecting from endpoint provider's list of auth schemes: "sigv4". User selected auth scheme is: "s3v4" -anexo76-backend | 2026-05-06 21:36:57,088 - botocore.regions - DEBUG - Selected auth type "v4" as "s3v4" with signing context params: {'region': 'us-east-1', 'signing_name': 's3', 'disableDoubleEncoding': True} -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.endpoint - DEBUG - Making request for OperationModel(name=HeadBucket) with params: {'url_path': '', 'query_string': {}, 'method': 'HEAD', 'headers': {'User-Agent': 'Boto3/1.35.36 md/Botocore#1.35.99 ua/2.0 os/linux#6.6.87.2-microsoft-standard-WSL2 md/arch#x86_64 lang/python#3.11.15 md/pyimpl#CPython cfg/retry-mode#legacy Botocore/1.35.99'}, 'body': b'', 'auth_path': '/anexo76/', 'url': 'http://anexo76-minio:9000/anexo76', 'context': {'client_region': 'us-east-1', 'client_config': , 'has_streaming_input': False, 'auth_type': 's3v4', 'unsigned_payload': None, 's3_redirect': {'redirected': False, 'bucket': 'anexo76', 'params': {'Bucket': 'anexo76'}}, 'input_params': {'Bucket': 'anexo76'}, 'signing': {'region': 'us-east-1', 'signing_name': 's3', 'disableDoubleEncoding': True}, 'endpoint_properties': {'authSchemes': [{'disableDoubleEncoding': True, 'name': 'sigv4', 'signingName': 's3', 'signingRegion': 'us-east-1'}]}}} -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event request-created.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event choose-signer.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-sign.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event before-sign.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.auth - DEBUG - Calculating signature using v4 auth. -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.auth - DEBUG - CanonicalRequest: -anexo76-backend | HEAD -anexo76-backend | /anexo76 -anexo76-backend | -anexo76-backend | host:anexo76-minio:9000 -anexo76-backend | x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -anexo76-backend | x-amz-date:20260506T213657Z -anexo76-backend | -anexo76-backend | host;x-amz-content-sha256;x-amz-date -anexo76-backend | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.auth - DEBUG - StringToSign: -anexo76-backend | AWS4-HMAC-SHA256 -anexo76-backend | 20260506T213657Z -anexo76-backend | 20260506/us-east-1/s3/aws4_request -anexo76-backend | 78f951a26193833ad927530efec5410bb55c4a7f8201543949aeeea0681e2809 -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.auth - DEBUG - Signature: -anexo76-backend | d6d66e8b6373a1ce555bba3571cf99e4819f2ca5d56772a4dde668a36d0c5b13 -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.hooks - DEBUG - Event request-created.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,089 - botocore.endpoint - DEBUG - Sending http request: -anexo76-backend | 2026-05-06 21:36:57,090 - urllib3.connectionpool - DEBUG - Starting new HTTP connection (1): anexo76-minio:9000 -anexo76-backend | 2026-05-06 21:36:57,092 - urllib3.connectionpool - DEBUG - http://anexo76-minio:9000 "HEAD /anexo76 HTTP/1.1" 200 0 -anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event before-parse.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event before-parse.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,093 - botocore.parsers - DEBUG - Response headers: {'Accept-Ranges': 'bytes', 'Content-Length': '0', 'Content-Type': 'application/xml', 'Server': 'MinIO', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains', 'Vary': 'Origin, Accept-Encoding', 'X-Amz-Id-2': 'dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8', 'X-Amz-Request-Id': '18AD17A315A8843E', 'X-Content-Type-Options': 'nosniff', 'X-Ratelimit-Limit': '3115', 'X-Ratelimit-Remaining': '3115', 'X-Xss-Protection': '1; mode=block', 'Date': 'Wed, 06 May 2026 21:36:57 GMT'} -anexo76-backend | 2026-05-06 21:36:57,093 - botocore.parsers - DEBUG - Response body: -anexo76-backend | b'' -anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:36:57,093 - botocore.retryhandler - DEBUG - No retry needed. -anexo76-backend | 2026-05-06 21:36:57,093 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:36:57,093 - core.storage_s3 - INFO - S3 bucket anexo76 exists -anexo76-backend | 2026-05-06 21:36:57,094 - main - INFO - Base de datos inicializada correctamente. -anexo76-backend | INFO: Application startup complete. -anexo76-backend | INFO: 127.0.0.1:33668 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 172.21.0.3:57858 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:33954 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | 2026-05-06 21:37:31,535 - httpcore.connection - DEBUG - connect_tcp.started host='workspace.aduanasoft.com' port=443 local_address=None timeout=5.0 socket_options=None -anexo76-backend | 2026-05-06 21:37:31,566 - httpcore.connection - DEBUG - connect_tcp.complete return_value= -anexo76-backend | 2026-05-06 21:37:31,566 - httpcore.connection - DEBUG - start_tls.started ssl_context= server_hostname='workspace.aduanasoft.com' timeout=5.0 -anexo76-backend | 2026-05-06 21:37:31,597 - httpcore.connection - DEBUG - start_tls.complete return_value= -anexo76-backend | 2026-05-06 21:37:31,597 - httpcore.http11 - DEBUG - send_request_headers.started request= -anexo76-backend | 2026-05-06 21:37:31,598 - httpcore.http11 - DEBUG - send_request_headers.complete -anexo76-backend | 2026-05-06 21:37:31,598 - httpcore.http11 - DEBUG - send_request_body.started request= -anexo76-backend | 2026-05-06 21:37:31,598 - httpcore.http11 - DEBUG - send_request_body.complete -anexo76-backend | 2026-05-06 21:37:31,598 - httpcore.http11 - DEBUG - receive_response_headers.started request= -anexo76-backend | 2026-05-06 21:37:31,662 - httpcore.http11 - DEBUG - receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Server', b'nginx/1.22.1'), (b'Date', b'Wed, 06 May 2026 21:37:34 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'250'), (b'Connection', b'keep-alive'), (b'x-request-id', b'296211c5-34bd-4c02-9cfb-176e09897234')]) -anexo76-backend | 2026-05-06 21:37:31,663 - httpx - INFO - HTTP Request: GET https://workspace.aduanasoft.com/api/v1/auth/me "HTTP/1.1 200 OK" -anexo76-backend | 2026-05-06 21:37:31,663 - httpcore.http11 - DEBUG - receive_response_body.started request= -anexo76-backend | 2026-05-06 21:37:31,663 - httpcore.http11 - DEBUG - receive_response_body.complete -anexo76-backend | 2026-05-06 21:37:31,664 - httpcore.http11 - DEBUG - response_closed.started -anexo76-backend | 2026-05-06 21:37:31,664 - httpcore.http11 - DEBUG - response_closed.complete -anexo76-backend | 2026-05-06 21:37:31,664 - httpcore.connection - DEBUG - close.started -anexo76-backend | 2026-05-06 21:37:31,664 - httpcore.connection - DEBUG - close.complete -anexo76-backend | 2026-05-06 21:37:31,665 - core.middleware - INFO - [license] tenant override propagated to Hub: 11 -anexo76-backend | 2026-05-06 21:37:31,670 - httpcore.connection - DEBUG - connect_tcp.started host='workspace.aduanasoft.com' port=443 local_address=None timeout=5.0 socket_options=None -anexo76-backend | 2026-05-06 21:37:31,700 - httpcore.connection - DEBUG - connect_tcp.complete return_value= -anexo76-backend | 2026-05-06 21:37:31,700 - httpcore.connection - DEBUG - start_tls.started ssl_context= server_hostname='workspace.aduanasoft.com' timeout=5.0 -anexo76-backend | 2026-05-06 21:37:31,730 - httpcore.connection - DEBUG - start_tls.complete return_value= -anexo76-backend | 2026-05-06 21:37:31,730 - httpcore.http11 - DEBUG - send_request_headers.started request= -anexo76-backend | 2026-05-06 21:37:31,731 - httpcore.http11 - DEBUG - send_request_headers.complete -anexo76-backend | 2026-05-06 21:37:31,731 - httpcore.http11 - DEBUG - send_request_body.started request= -anexo76-backend | 2026-05-06 21:37:31,731 - httpcore.http11 - DEBUG - send_request_body.complete -anexo76-backend | 2026-05-06 21:37:31,731 - httpcore.http11 - DEBUG - receive_response_headers.started request= -anexo76-backend | 2026-05-06 21:37:31,824 - httpcore.http11 - DEBUG - receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Server', b'nginx/1.22.1'), (b'Date', b'Wed, 06 May 2026 21:37:35 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'224'), (b'Connection', b'keep-alive'), (b'x-request-id', b'f4bfac19-d54b-4216-bbd4-011f9ff783e8')]) -anexo76-backend | 2026-05-06 21:37:31,825 - httpx - INFO - HTTP Request: GET https://workspace.aduanasoft.com/api/v1/auth/verify-license "HTTP/1.1 200 OK" -anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.http11 - DEBUG - receive_response_body.started request= -anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.http11 - DEBUG - receive_response_body.complete -anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.http11 - DEBUG - response_closed.started -anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.http11 - DEBUG - response_closed.complete -anexo76-backend | 2026-05-06 21:37:31,825 - httpcore.connection - DEBUG - close.started -anexo76-backend | 2026-05-06 21:37:31,826 - httpcore.connection - DEBUG - close.complete -anexo76-backend | 2026-05-06 21:37:31,826 - core.middleware - INFO - 🔑 verify-license → status=200 body={"valid":true,"message":"Licencia activa y válida","tenant_slug":"aduanasoft","tenant_name":"aduanasoft","product_name":null,"expires_at":"2027-04-29T17:32:31.670550","plan":"basic","max_users":20,"features":["api_access"]} -anexo76-backend | 2026-05-06 21:37:31,826 - core.middleware - INFO - Request: GET /api/v1/a76/company/my-companies -anexo76-backend | 2026-05-06 21:37:31,836 - core.security - INFO - [get_current_user] X-Tenant-Override='11' -anexo76-backend | 2026-05-06 21:37:31,843 - httpcore.connection - DEBUG - connect_tcp.started host='workspace.aduanasoft.com' port=443 local_address=None timeout=5.0 socket_options=None -anexo76-backend | 2026-05-06 21:37:31,872 - httpcore.connection - DEBUG - connect_tcp.complete return_value= -anexo76-backend | 2026-05-06 21:37:31,873 - httpcore.connection - DEBUG - start_tls.started ssl_context= server_hostname='workspace.aduanasoft.com' timeout=5.0 -anexo76-backend | 2026-05-06 21:37:31,902 - httpcore.connection - DEBUG - start_tls.complete return_value= -anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - send_request_headers.started request= -anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - send_request_headers.complete -anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - send_request_body.started request= -anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - send_request_body.complete -anexo76-backend | 2026-05-06 21:37:31,903 - httpcore.http11 - DEBUG - receive_response_headers.started request= -anexo76-backend | 2026-05-06 21:37:31,983 - httpcore.http11 - DEBUG - receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Server', b'nginx/1.22.1'), (b'Date', b'Wed, 06 May 2026 21:37:35 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'250'), (b'Connection', b'keep-alive'), (b'x-request-id', b'9f3faac1-6e02-4160-87b4-22af7df1ef11')]) -anexo76-backend | 2026-05-06 21:37:31,984 - httpx - INFO - HTTP Request: GET https://workspace.aduanasoft.com/api/v1/auth/me "HTTP/1.1 200 OK" -anexo76-backend | 2026-05-06 21:37:31,984 - httpcore.http11 - DEBUG - receive_response_body.started request= -anexo76-backend | 2026-05-06 21:37:31,984 - httpcore.http11 - DEBUG - receive_response_body.complete -anexo76-backend | 2026-05-06 21:37:31,984 - httpcore.http11 - DEBUG - response_closed.started -anexo76-backend | 2026-05-06 21:37:31,984 - httpcore.http11 - DEBUG - response_closed.complete -anexo76-backend | 2026-05-06 21:37:31,985 - httpcore.connection - DEBUG - close.started -anexo76-backend | 2026-05-06 21:37:31,985 - httpcore.connection - DEBUG - close.complete -anexo76-backend | 2026-05-06 21:37:32,585 - core.middleware - INFO - Response: GET /api/v1/a76/company/my-companies Status: 200 Duration: 0.759s -anexo76-backend | INFO: 172.21.0.3:45462 - "GET /api/v1/a76/company/my-companies HTTP/1.1" 200 OK -anexo76-backend | 2026-05-06 21:37:32,590 - core.middleware - INFO - Request: GET /api/v1/auth/me -anexo76-backend | 2026-05-06 21:37:32,591 - core.middleware - INFO - Response: GET /api/v1/auth/me Status: 200 Duration: 0.001s -anexo76-backend | INFO: 172.21.0.3:45470 - "GET /api/v1/auth/me HTTP/1.1" 200 OK -anexo76-backend | 2026-05-06 21:37:32,595 - core.middleware - INFO - [license] tenant override propagated to Hub: 11 -anexo76-backend | 2026-05-06 21:37:32,601 - httpcore.connection - DEBUG - connect_tcp.started host='workspace.aduanasoft.com' port=443 local_address=None timeout=5.0 socket_options=None -anexo76-backend | 2026-05-06 21:37:32,631 - httpcore.connection - DEBUG - connect_tcp.complete return_value= -anexo76-backend | 2026-05-06 21:37:32,631 - httpcore.connection - DEBUG - start_tls.started ssl_context= server_hostname='workspace.aduanasoft.com' timeout=5.0 -anexo76-backend | 2026-05-06 21:37:32,661 - httpcore.connection - DEBUG - start_tls.complete return_value= -anexo76-backend | 2026-05-06 21:37:32,662 - httpcore.http11 - DEBUG - send_request_headers.started request= -anexo76-backend | 2026-05-06 21:37:32,662 - httpcore.http11 - DEBUG - send_request_headers.complete -anexo76-backend | 2026-05-06 21:37:32,662 - httpcore.http11 - DEBUG - send_request_body.started request= -anexo76-backend | 2026-05-06 21:37:32,663 - httpcore.http11 - DEBUG - send_request_body.complete -anexo76-backend | 2026-05-06 21:37:32,663 - httpcore.http11 - DEBUG - receive_response_headers.started request= -anexo76-backend | 2026-05-06 21:37:32,756 - httpcore.http11 - DEBUG - receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Server', b'nginx/1.22.1'), (b'Date', b'Wed, 06 May 2026 21:37:36 GMT'), (b'Content-Type', b'application/json'), (b'Content-Length', b'224'), (b'Connection', b'keep-alive'), (b'x-request-id', b'b99812fe-d833-46f2-9008-b3fd669d9972')]) -anexo76-backend | 2026-05-06 21:37:32,757 - httpx - INFO - HTTP Request: GET https://workspace.aduanasoft.com/api/v1/auth/verify-license "HTTP/1.1 200 OK" -anexo76-backend | 2026-05-06 21:37:32,757 - httpcore.http11 - DEBUG - receive_response_body.started request= -anexo76-backend | 2026-05-06 21:37:32,757 - httpcore.http11 - DEBUG - receive_response_body.complete -anexo76-backend | 2026-05-06 21:37:32,757 - httpcore.http11 - DEBUG - response_closed.started -anexo76-backend | 2026-05-06 21:37:32,757 - httpcore.http11 - DEBUG - response_closed.complete -anexo76-backend | 2026-05-06 21:37:32,758 - httpcore.connection - DEBUG - close.started -anexo76-backend | 2026-05-06 21:37:32,758 - httpcore.connection - DEBUG - close.complete -anexo76-backend | 2026-05-06 21:37:32,758 - core.middleware - INFO - 🔑 verify-license → status=200 body={"valid":true,"message":"Licencia activa y válida","tenant_slug":"aduanasoft","tenant_name":"aduanasoft","product_name":null,"expires_at":"2027-04-29T17:32:31.670550","plan":"basic","max_users":20,"features":["api_access"]} -anexo76-backend | 2026-05-06 21:37:32,758 - core.middleware - INFO - Request: GET /api/v1/core/users/me/profile -anexo76-backend | 2026-05-06 21:37:32,759 - core.security - INFO - [get_current_user] X-Tenant-Override='11' -anexo76-backend | 2026-05-06 21:37:32,770 - core.middleware - INFO - Response: GET /api/v1/core/users/me/profile Status: 200 Duration: 0.011s -anexo76-backend | INFO: 172.21.0.3:45462 - "GET /api/v1/core/users/me/profile HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:35456 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | 2026-05-06 21:37:47,554 - core.middleware - INFO - Request: GET /api/avatars/default.jpg -anexo76-backend | 2026-05-06 21:37:47,558 - core.middleware - INFO - Response: GET /api/avatars/default.jpg Status: 404 Duration: 0.004s -anexo76-backend | INFO: 172.21.0.3:53544 - "GET /api/avatars/default.jpg HTTP/1.1" 404 Not Found -anexo76-backend | INFO: 172.21.0.3:53560 - "POST /api-sveltekit/auth/silent-refresh HTTP/1.1" 401 Unauthorized -anexo76-backend | INFO: 172.21.0.3:53566 - "POST /api-sveltekit/company/set-active HTTP/1.1" 401 Unauthorized -anexo76-backend | 2026-05-06 21:37:49,296 - core.middleware - INFO - Request: GET /api/avatars/default.jpg -anexo76-backend | 2026-05-06 21:37:49,298 - core.middleware - INFO - Response: GET /api/avatars/default.jpg Status: 404 Duration: 0.002s -anexo76-backend | INFO: 172.21.0.3:53576 - "GET /api/avatars/default.jpg HTTP/1.1" 404 Not Found -anexo76-backend | INFO: 127.0.0.1:37842 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:60858 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:47212 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:38264 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:45138 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:54772 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:39924 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | WARNING: WatchFiles detected changes in 'api/v1/modules/core/permissions/routes.py'. Reloading... -anexo76-backend | INFO: Shutting down -anexo76-backend | INFO: Waiting for application shutdown. -anexo76-backend | INFO: Application shutdown complete. -anexo76-backend | INFO: Finished server process [9] -anexo76-backend | DEBUG: Celery Broker URL: redis://valkey:6379/0 -anexo76-backend | INFO: Started server process [94] -anexo76-backend | INFO: Waiting for application startup. -anexo76-backend | 2026-05-06 21:40:24,734 - main - INFO - Iniciando la aplicación Anexo76... -anexo76-backend | INFO [alembic.runtime.migration] Context impl PostgresqlImpl. -anexo76-backend | INFO [alembic.runtime.migration] Will assume transactional DDL. -anexo76-backend | 2026-05-06 21:40:26,311 - botocore.hooks - DEBUG - Changing event name from creating-client-class.iot-data to creating-client-class.iot-data-plane -anexo76-backend | 2026-05-06 21:40:26,312 - botocore.hooks - DEBUG - Changing event name from before-call.apigateway to before-call.api-gateway -anexo76-backend | 2026-05-06 21:40:26,313 - botocore.hooks - DEBUG - Changing event name from request-created.machinelearning.Predict to request-created.machine-learning.Predict -anexo76-backend | 2026-05-06 21:40:26,313 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.autoscaling.CreateLaunchConfiguration to before-parameter-build.auto-scaling.CreateLaunchConfiguration -anexo76-backend | 2026-05-06 21:40:26,313 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.route53 to before-parameter-build.route-53 -anexo76-backend | 2026-05-06 21:40:26,313 - botocore.hooks - DEBUG - Changing event name from request-created.cloudsearchdomain.Search to request-created.cloudsearch-domain.Search -anexo76-backend | 2026-05-06 21:40:26,314 - botocore.hooks - DEBUG - Changing event name from docs.*.autoscaling.CreateLaunchConfiguration.complete-section to docs.*.auto-scaling.CreateLaunchConfiguration.complete-section -anexo76-backend | 2026-05-06 21:40:26,315 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.logs.CreateExportTask to before-parameter-build.cloudwatch-logs.CreateExportTask -anexo76-backend | 2026-05-06 21:40:26,315 - botocore.hooks - DEBUG - Changing event name from docs.*.logs.CreateExportTask.complete-section to docs.*.cloudwatch-logs.CreateExportTask.complete-section -anexo76-backend | 2026-05-06 21:40:26,315 - botocore.hooks - DEBUG - Changing event name from before-parameter-build.cloudsearchdomain.Search to before-parameter-build.cloudsearch-domain.Search -anexo76-backend | 2026-05-06 21:40:26,315 - botocore.hooks - DEBUG - Changing event name from docs.*.cloudsearchdomain.Search.complete-section to docs.*.cloudsearch-domain.Search.complete-section -anexo76-backend | 2026-05-06 21:40:26,320 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/endpoints.json -anexo76-backend | 2026-05-06 21:40:26,331 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/sdk-default-configuration.json -anexo76-backend | 2026-05-06 21:40:26,331 - botocore.hooks - DEBUG - Event choose-service-name: calling handler -anexo76-backend | 2026-05-06 21:40:26,364 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/service-2.json.gz -anexo76-backend | 2026-05-06 21:40:26,386 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/service-2.sdk-extras.json -anexo76-backend | 2026-05-06 21:40:26,395 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/s3/2006-03-01/endpoint-rule-set-1.json.gz -anexo76-backend | 2026-05-06 21:40:26,415 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/partitions.json -anexo76-backend | 2026-05-06 21:40:26,416 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler -anexo76-backend | 2026-05-06 21:40:26,417 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler ._handler at 0x7e12d5327e20> -anexo76-backend | 2026-05-06 21:40:26,450 - botocore.hooks - DEBUG - Event creating-client-class.s3: calling handler -anexo76-backend | 2026-05-06 21:40:26,451 - botocore.endpoint - DEBUG - Setting s3 timeout as (60, 60) -anexo76-backend | 2026-05-06 21:40:26,455 - botocore.loaders - DEBUG - Loading JSON file: /usr/local/lib/python3.11/site-packages/botocore/data/_retry.json -anexo76-backend | 2026-05-06 21:40:26,455 - botocore.client - DEBUG - Registering retry handlers for service: s3 -anexo76-backend | 2026-05-06 21:40:26,455 - botocore.utils - DEBUG - Registering S3 region redirector handler -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.utils - DEBUG - Registering S3Express Identity Resolver -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-parameter-build.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-endpoint-resolution.s3: calling handler -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.hooks - DEBUG - Event before-endpoint-resolution.s3: calling handler > -anexo76-backend | 2026-05-06 21:40:26,456 - botocore.regions - DEBUG - Calling endpoint provider with parameters: {'Bucket': 'anexo76', 'Region': 'us-east-1', 'UseFIPS': False, 'UseDualStack': False, 'Endpoint': 'http://anexo76-minio:9000', 'ForcePathStyle': True, 'Accelerate': False, 'UseGlobalEndpoint': True, 'DisableMultiRegionAccessPoints': False, 'UseArnRegion': True} -anexo76-backend | 2026-05-06 21:40:26,457 - botocore.regions - DEBUG - Endpoint provider result: http://anexo76-minio:9000/anexo76 -anexo76-backend | 2026-05-06 21:40:26,457 - botocore.regions - DEBUG - Selecting from endpoint provider's list of auth schemes: "sigv4". User selected auth scheme is: "s3v4" -anexo76-backend | 2026-05-06 21:40:26,457 - botocore.regions - DEBUG - Selected auth type "v4" as "s3v4" with signing context params: {'region': 'us-east-1', 'signing_name': 's3', 'disableDoubleEncoding': True} -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-call.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.endpoint - DEBUG - Making request for OperationModel(name=HeadBucket) with params: {'url_path': '', 'query_string': {}, 'method': 'HEAD', 'headers': {'User-Agent': 'Boto3/1.35.36 md/Botocore#1.35.99 ua/2.0 os/linux#6.6.87.2-microsoft-standard-WSL2 md/arch#x86_64 lang/python#3.11.15 md/pyimpl#CPython cfg/retry-mode#legacy Botocore/1.35.99'}, 'body': b'', 'auth_path': '/anexo76/', 'url': 'http://anexo76-minio:9000/anexo76', 'context': {'client_region': 'us-east-1', 'client_config': , 'has_streaming_input': False, 'auth_type': 's3v4', 'unsigned_payload': None, 's3_redirect': {'redirected': False, 'bucket': 'anexo76', 'params': {'Bucket': 'anexo76'}}, 'input_params': {'Bucket': 'anexo76'}, 'signing': {'region': 'us-east-1', 'signing_name': 's3', 'disableDoubleEncoding': True}, 'endpoint_properties': {'authSchemes': [{'disableDoubleEncoding': True, 'name': 'sigv4', 'signingName': 's3', 'signingRegion': 'us-east-1'}]}}} -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event request-created.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event choose-signer.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-sign.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,458 - botocore.hooks - DEBUG - Event before-sign.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:40:26,459 - botocore.auth - DEBUG - Calculating signature using v4 auth. -anexo76-backend | 2026-05-06 21:40:26,459 - botocore.auth - DEBUG - CanonicalRequest: -anexo76-backend | HEAD -anexo76-backend | /anexo76 -anexo76-backend | -anexo76-backend | host:anexo76-minio:9000 -anexo76-backend | x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -anexo76-backend | x-amz-date:20260506T214026Z -anexo76-backend | -anexo76-backend | host;x-amz-content-sha256;x-amz-date -anexo76-backend | e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -anexo76-backend | 2026-05-06 21:40:26,459 - botocore.auth - DEBUG - StringToSign: -anexo76-backend | AWS4-HMAC-SHA256 -anexo76-backend | 20260506T214026Z -anexo76-backend | 20260506/us-east-1/s3/aws4_request -anexo76-backend | 9c598ef422ed5a1f958ce1e61ea627a1c47025c80840ef18d19d1417b9d5c0b8 -anexo76-backend | 2026-05-06 21:40:26,459 - botocore.auth - DEBUG - Signature: -anexo76-backend | 4b5dcb6959901de692d7e3377b48be53bbf6665daf7be709a25af49ee8561df3 -anexo76-backend | 2026-05-06 21:40:26,459 - botocore.hooks - DEBUG - Event request-created.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,459 - botocore.endpoint - DEBUG - Sending http request: -anexo76-backend | 2026-05-06 21:40:26,461 - urllib3.connectionpool - DEBUG - Starting new HTTP connection (1): anexo76-minio:9000 -anexo76-backend | 2026-05-06 21:40:26,463 - urllib3.connectionpool - DEBUG - http://anexo76-minio:9000 "HEAD /anexo76 HTTP/1.1" 200 0 -anexo76-backend | 2026-05-06 21:40:26,463 - botocore.hooks - DEBUG - Event before-parse.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,463 - botocore.hooks - DEBUG - Event before-parse.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,463 - botocore.parsers - DEBUG - Response headers: {'Accept-Ranges': 'bytes', 'Content-Length': '0', 'Content-Type': 'application/xml', 'Server': 'MinIO', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains', 'Vary': 'Origin, Accept-Encoding', 'X-Amz-Id-2': 'dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8', 'X-Amz-Request-Id': '18AD17D3D5264B2C', 'X-Content-Type-Options': 'nosniff', 'X-Ratelimit-Limit': '3115', 'X-Ratelimit-Remaining': '3115', 'X-Xss-Protection': '1; mode=block', 'Date': 'Wed, 06 May 2026 21:40:26 GMT'} -anexo76-backend | 2026-05-06 21:40:26,463 - botocore.parsers - DEBUG - Response body: -anexo76-backend | b'' -anexo76-backend | 2026-05-06 21:40:26,464 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,464 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler -anexo76-backend | 2026-05-06 21:40:26,464 - botocore.retryhandler - DEBUG - No retry needed. -anexo76-backend | 2026-05-06 21:40:26,464 - botocore.hooks - DEBUG - Event needs-retry.s3.HeadBucket: calling handler > -anexo76-backend | 2026-05-06 21:40:26,464 - core.storage_s3 - INFO - S3 bucket anexo76 exists -anexo76-backend | 2026-05-06 21:40:26,464 - main - INFO - Base de datos inicializada correctamente. -anexo76-backend | INFO: Application startup complete. -anexo76-backend | INFO: 127.0.0.1:49166 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:39678 - "GET /api/health HTTP/1.1" 200 OK -anexo76-backend | INFO: 127.0.0.1:59246 - "GET /api/health HTTP/1.1" 200 OK diff --git a/frontend/src/lib/components/help/HelpDrawer.svelte b/frontend/src/lib/components/help/HelpDrawer.svelte index ae857ae8..da3d68db 100644 --- a/frontend/src/lib/components/help/HelpDrawer.svelte +++ b/frontend/src/lib/components/help/HelpDrawer.svelte @@ -33,6 +33,8 @@ let isLoading = $state(false); let isCreating = $state(false); let searchTerm = $state(''); + let hasError = $state(false); + let isLoaded = $state(false); const isAdmin = $derived($currentUser?.roles?.includes('admin') || false); const currentPath = $derived(page.url.pathname + page.url.search); @@ -155,8 +157,11 @@ async function loadArticles() { isLoading = true; try { + hasError = false; articles = await helpApi.listArticles(); + isLoaded = true; } catch (e) { + hasError = true; toast.error('Error al cargar artículos de ayuda'); } finally { isLoading = false; @@ -222,9 +227,14 @@ } $effect(() => { - if (helpStore.isOpen && articles.length === 0 && !isLoading) { + if (helpStore.isOpen && !isLoaded && !isLoading && !hasError) { loadArticles(); } + + // Reset error when drawer closes to allow retry next time it opens + if (!helpStore.isOpen) { + hasError = false; + } }); function renderMarkdown(content: string) { @@ -336,10 +346,20 @@
-

Biblioteca vacía

-

No hay artículos registrados en el sistema aún.

+

+ {hasError ? 'Error de conexión' : 'Biblioteca vacía'} +

+

+ {hasError + ? 'No pudimos conectar con el servidor de ayuda.' + : 'No hay artículos registrados para esta sección aún.'} +

- {#if isAdmin} + {#if hasError} + + {:else if isAdmin} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 87132f83..24c69218 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -44,11 +44,11 @@ export default defineConfig({ // Hosts distintos y recibir 403. `true` permite cualquier Host en dev. allowedHosts: true, proxy: { - '/api/': { + '/api/uploads': { target: 'http://backend:8000', changeOrigin: true }, - '/media': { + '/api/v1/core/help-center': { target: 'http://backend:8000', changeOrigin: true } From 69833a530d0fa8963d4ac1782d94200698262ea4 Mon Sep 17 00:00:00 2001 From: Kevin_Ramirez Date: Thu, 7 May 2026 11:54:51 -0500 Subject: [PATCH 6/6] Traducciones corregidas --- frontend/messages/en.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/messages/en.json b/frontend/messages/en.json index c4751712..d24b48c9 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -104,11 +104,11 @@ }, "sidebar": { "dashboard": "Dashboard", - "help_center": "Manuales del Sistema", - "management_label": "Gestión", + "help_center": "System Manuals", + "management_label": "Management", "bulk_upload": { - "title": "Cargas masivas", - "entry": "Importación CSV" + "title": "Bulk Uploads", + "entry": "CSV Import" }, "reference_data": { "title": "Fixed Catalogs", @@ -1802,4 +1802,4 @@ "download_csv": "Download CSV" } } -} +} \ No newline at end of file