feat(doctor): add fn doctor CLI + 14 functions for system management
Adds `fn doctor` read-only diagnostic command with subcommands artefacts, services, sync, uses-functions, unused, and --json flag for agents. Each subcommand wraps a registry function in functions/infra/. New functions: - artefact_doctor, services_status, pc_locations_drift, audit_uses_functions, find_unused_functions (Go diagnostics) - backup_sqlite_db, rotate_backups, wait_for_http, wait_for_port, port_kill, tail_journal, pre_commit_hook_install (bash utilities) - notify_telegram (Go HTTP) - backup_all pipeline (tag launcher) Plus prior session leftovers (scan_secrets_in_dirty, append_diary_entry, git utilities, http_session_cookie_middleware, compile/full-git pipelines). Fixes pc_locations_drift filepath.Join bug with absolute dir_path. Documents fn doctor in CLAUDE.md, .claude/rules/fn_doctor.md (rule 23), docs/architecture.md, CHANGELOG.md (2026-05-07), and diary entry. First fn doctor uses-functions run found drift in 7/12 apps (deuda para sincronizar app.md con imports reales). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
---
|
||||
name: http_session_cookie_middleware
|
||||
kind: function
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "func HTTPSessionCookieMiddleware(cfg SessionCookieConfig) Middleware"
|
||||
description: "Middleware HTTP que valida sesiones via cookie o header Authorization: Bearer. Inyecta el userID en el contexto si la sesion es valida. Delega sin validar los paths en SkipPaths."
|
||||
params:
|
||||
- name: cfg
|
||||
desc: "Configuracion: DB con tabla sessions, nombre de cookie, prefijos a saltarse y clave tipada para el contexto."
|
||||
output: "Middleware (func(http.Handler) http.Handler) que protege los endpoints no listados en SkipPaths."
|
||||
tags: [http, auth, session, cookie, middleware, bearer]
|
||||
uses_functions:
|
||||
- session_validate_go_infra
|
||||
- http_error_response_go_infra
|
||||
uses_types:
|
||||
- Session_go_infra
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports:
|
||||
- context
|
||||
- database/sql
|
||||
- net/http
|
||||
- strings
|
||||
tested: true
|
||||
tests:
|
||||
- "sesion valida via cookie deja pasar y expone userID en contexto"
|
||||
- "sin cookie ni header devuelve 401"
|
||||
- "skip path bypassa sin validar token"
|
||||
test_file_path: "functions/infra/http_session_cookie_middleware_test.go"
|
||||
file_path: "functions/infra/http_session_cookie_middleware.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
type ctxKey string
|
||||
const userKey ctxKey = "user_id"
|
||||
|
||||
mw := infra.HTTPSessionCookieMiddleware(infra.SessionCookieConfig{
|
||||
DB: db,
|
||||
CookieName: "kanban_session",
|
||||
SkipPaths: []string{"/api/auth/", "/health"},
|
||||
UserCtxKey: userKey,
|
||||
})
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/api/", mw(apiRouter))
|
||||
|
||||
// En un handler:
|
||||
userID, ok := infra.UserIDFromContext(r.Context(), userKey)
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
`SessionCookieConfig.UserCtxKey` debe ser una clave tipada propia del caller (no `string`) para evitar colisiones en el contexto. Patron canonico: `type ctxKey string; const userKey ctxKey = "user_id"`.
|
||||
|
||||
El helper `UserIDFromContext(ctx, key)` esta en el mismo paquete y hace el type-assert de forma segura retornando `("", false)` si no hay valor o el tipo no coincide.
|
||||
|
||||
El orden de extraccion del token es: cookie → `Authorization: Bearer`. Si ninguno esta presente responde 401 con `{"code":"unauthorized","message":"session required"}`.
|
||||
Reference in New Issue
Block a user