diff --git a/.agents/README.md b/.agents/README.md new file mode 100644 index 0000000..584f77f --- /dev/null +++ b/.agents/README.md @@ -0,0 +1,42 @@ +# .agents/ — Skills y Orquestación + +## Skills incluidas (pinned — no dependen de servicios externos) + +``` +.agents/skills/ +├── test-driven-development/SKILL.md ← obra/superpowers (pinned 2026-03-19) +├── systematic-debugging/SKILL.md ← obra/superpowers (pinned 2026-03-19) +├── code-review-excellence/SKILL.md ← community + checklist V4 BIAN (pinned 2026-03-19) +├── documentation-writer/SKILL.md ← community + OpenAPI V4 (pinned 2026-03-19) +└── security-best-practices/SKILL.md ← community + banking patterns (pinned 2026-03-19) +``` + +**¿Por qué están congeladas?** Para evitar que una actualización upstream cambie el comportamiento esperado. Estas versiones fueron validadas contra el patrón V4. + +**¿Cuándo actualizarlas?** Solo cuando el equipo revise la nueva versión upstream y confirme que es compatible con los patrones del proyecto. + +--- + +## Orquestación Multi-Agente (V5 — activar cuando proceda) + +Para implementar orquestación, ver `docs/guia-v5-advanced-ai-architecture.md §3 y §4`: + +``` +.agents/ +├── orchestrator.md ← director (NUNCA hace trabajo real, solo coordina) +├── agents/ +│ ├── spec-writer.md +│ ├── designer.md +│ ├── impl-rec.md +│ ├── impl-bus.md +│ ├── test-writer.md +│ └── reviewer.md +└── contracts/ + ├── spec-output.md + ├── design-output.md + └── review-output.md +``` + +### Herramientas +- **Agent Teams Lite:** https://github.com/Gentleman-Programming/agent-teams-lite +- **Engram (memoria persistente):** `npx -y @gentleman-programming/engram` diff --git a/.agents/skills/code-review-excellence/SKILL.md b/.agents/skills/code-review-excellence/SKILL.md new file mode 100644 index 0000000..2307f77 --- /dev/null +++ b/.agents/skills/code-review-excellence/SKILL.md @@ -0,0 +1,122 @@ +--- +name: code-review-excellence +description: Systematic code review for correctness, security, performance and maintainability. Produces structured review reports. +source: community (pinned 2026-03-19) +--- + +# Code Review Excellence + +## Overview +Transform code reviews from rubber-stamping into knowledge sharing through constructive feedback, systematic analysis, and collaborative improvement. + +## When to Use +- Reviewing pull requests +- Establishing code review standards +- Mentoring developers through review +- Auditing for correctness, security, or performance +- Pre-delivery validation against architectural patterns + +## Instructions + +### 1. Read Context First +Before touching code: +- Read the PR description, linked issues, and requirements +- Understand the architectural pattern being followed +- Check if there's a reference implementation to compare against +- Read test signals (CI status, coverage reports) + +### 2. Review Systematically +Check in this order: + +**Correctness:** +- Does the code do what the requirements ask? +- Are edge cases handled? +- Are error paths covered? +- Does it match the reference implementation pattern? + +**Security:** +- Input validation present? (`@Valid`, `@NotNull`, `@Pattern`) +- Sensitive data masked in logs? (`authorization`, `customerId`) +- No secrets hardcoded? +- Authentication/authorization checks present? + +**Performance:** +- No blocking I/O in hot paths (check `@PostConstruct` usage) +- No N+1 queries or repeated file reads +- Appropriate timeouts on external calls +- Async operations use proper context propagation (MDC) + +**Maintainability:** +- Clear naming conventions +- Single responsibility per class +- Dependencies injected, not constructed +- Proper layer separation (no business logic in adapters) + +### 3. Provide Actionable Feedback +For each issue: +- State the severity: BLOCKING | IMPORTANT | MINOR +- Explain WHY it's a problem, not just WHAT is wrong +- Suggest a concrete fix or alternative +- Ask clarifying questions when intent is unclear + +### 4. Acknowledge Good Patterns +- Call out well-implemented patterns explicitly +- Recognize clean abstractions and good test coverage +- Note when the code follows architectural guidelines correctly + +## Output Format + +```markdown +## Code Review Summary + +### Overall Assessment +[1-2 sentence summary of the change quality] + +### Blocking Issues (must fix before merge) +- **[FILE:LINE]** — [Description] → [Suggested fix] + +### Important Issues (should fix) +- **[FILE:LINE]** — [Description] → [Suggested fix] + +### Minor Issues (nice to have) +- **[FILE:LINE]** — [Description] → [Suggested fix] + +### Questions +- [Clarifying questions about intent or requirements] + +### Positive Patterns Noted +- [Good patterns worth highlighting] + +### Test Coverage +- [Coverage assessment and gaps] +``` + +## Review Checklist for V4 BIAN APIs + +When reviewing an API implementation against `guia-4-implemented-pattern.md`: + +### REC Layer +- [ ] Resource only has `@Valid` and delegates to UseCase — no logic +- [ ] Request DTOs use `@NotNull(message = "VDE01")` and `@Valid` on nested objects +- [ ] BusXxxClient is an **interface** with `@RegisterRestClient(configKey = "...")` +- [ ] BusXxxAdapter injects with `@RestClient` and reads `agencyCode` from MDC +- [ ] `ValidationExceptionMapper` present in `common/infrastructure/interceptor/` +- [ ] `RestClientExceptionMapper` present and registered via `@RegisterProvider` +- [ ] `InboundLoggingFilter` uses `SequenceInputStream` to reconstruct the stream + +### BUS Layer +- [ ] Service orchestrates Ports — does not implement HTTP directly +- [ ] Service availability checked **before** business logic +- [ ] Security trace executes in `finally` using `AsyncMdcRunner.run()` +- [ ] DomXxxClient has `@RegisterProvider(RestClientLoggingFilter.class)` and `@RegisterProvider(RestClientExceptionMapper.class)` +- [ ] Mapper uses `@Mapper(componentModel = "cdi")` with `@AfterMapping` for complex fields +- [ ] `MessageHelper` uses `@PostConstruct` — no file reading in constructor +- [ ] Error responses always include `status = "error"` and `traceId` + +## Common Review Anti-Patterns +| Anti-Pattern | Better Approach | +|---|---| +| "Looks good to me" (LGTM without review) | Run through the checklist systematically | +| Nitpicking style while ignoring logic bugs | Prioritize correctness over formatting | +| Rewriting the PR in comments | Suggest one concrete alternative, not a full rewrite | +| Blocking on subjective preferences | Only block on correctness, security, performance | diff --git a/.agents/skills/documentation-writer/SKILL.md b/.agents/skills/documentation-writer/SKILL.md new file mode 100644 index 0000000..5da662b --- /dev/null +++ b/.agents/skills/documentation-writer/SKILL.md @@ -0,0 +1,167 @@ +--- +name: documentation-writer +description: Generate structured API documentation, OpenAPI annotations, and technical specifications from contracts and code. +source: community + V4 patterns (pinned 2026-03-19) +--- + +# Documentation Writer + +## Overview +Generate structured documentation from API contracts, code, and specifications. Focuses on OpenAPI annotations, technical specs, and developer-facing documentation. + +## When to Use +- Writing OpenAPI/Swagger annotations for JAX-RS Resources +- Generating API specification documents from contracts +- Creating developer onboarding documentation +- Producing technical decision records (ADRs) +- Enriching `@APIResponse` annotations with real examples + +## Instructions + +### 1. Gather Context +Before generating documentation: +- Read the API contract (headers, body, response structure) +- Read the error catalog (`messages.content` in `application.yml`) +- Check the reference implementation for actual response shapes +- Identify all possible HTTP status codes + +### 2. Generate OpenAPI Annotations + +For each endpoint, produce complete `@Operation` and `@APIResponse` annotations: + +```java +@Operation( + summary = "Evaluate customer behavior against blacklist", + description = "Validates customer restrictions (L1) against the domain blacklist service" +) +@APIResponse( + responseCode = "200", + description = "Successful evaluation", + content = @Content( + mediaType = "application/json", + schema = @Schema(implementation = RecCustomerBehaviorResponse.class), + examples = @ExampleObject( + name = "Successful evaluation", + value = """ + { + "statusResponse": { + "status": "ok", + "statusCode": "200", + "message": "Operacion exitosa", + "traceId": "SESSION-ABC-123" + } + } + """ + ) + ) +) +@APIResponse( + responseCode = "400", + description = "Validation error - required field missing", + content = @Content( + schema = @Schema(implementation = ApiResponse.class), + examples = @ExampleObject( + name = "Missing required field", + value = """ + { + "statusResponse": { + "status": "error", + "statusCode": "VDE01", + "message": "Error en dato de entrada obligatorio: customerReference", + "traceId": "SESSION-ABC-123" + } + } + """ + ) + ) +) +@APIResponse( + responseCode = "409", + description = "Backend internal error", + content = @Content( + schema = @Schema(implementation = ApiResponse.class), + examples = @ExampleObject( + name = "Backend conflict", + value = """ + { + "statusResponse": { + "status": "error", + "statusCode": "PIB-00", + "message": "Error Interno backend", + "traceId": "SESSION-ABC-123" + } + } + """ + ) + ) +) +@APIResponse( + responseCode = "503", + description = "Service unavailable - maintenance window", + content = @Content( + schema = @Schema(implementation = ApiResponse.class), + examples = @ExampleObject( + name = "Service in maintenance", + value = """ + { + "statusResponse": { + "status": "error", + "statusCode": "VRN04", + "message": "Servicio en horario de mantenimiento", + "traceId": "SESSION-ABC-123" + } + } + """ + ) + ) +) +``` + +### 3. Map Error Codes to Annotations + +Use the error catalog from `application.yml` → `messages.content`: + +| Error Code | HTTP | `@APIResponse(responseCode=)` | Example message | +|---|---|---|---| +| `200` | 200 | `"200"` | `"Operacion exitosa"` | +| `VDE01` | 400 | `"400"` | `"Error en dato de entrada obligatorio: %s"` | +| `VDE02` | 400 | `"400"` | `"Error en valor permitido para campo: %s"` | +| `VRN04` | 503 | `"503"` | `"Servicio en horario de mantenimiento"` | +| `PIB-00` | 409 | `"409"` | `"Error Interno backend"` | + +### 4. Documentation Quality Checklist + +- [ ] Every endpoint has `@Operation(summary, description)` +- [ ] Every possible HTTP status has an `@APIResponse` +- [ ] Every `@APIResponse` includes `@ExampleObject` with realistic data +- [ ] Error examples show `status: "error"` + `traceId` consistently +- [ ] Header parameters have `@Parameter(description, required)` +- [ ] Request body schema matches the actual DTO +- [ ] `@Schema` descriptions are in business language, not technical jargon + +## Output Format + +When generating spec documents, use this structure: + +```markdown +# API Specification — + +## Endpoint +| Method | Path | Description | +|---|---|---| + +## Headers +| Name | Required | Description | + +## Request Body +| Field | Type | Required | Validation | Error Code | + +## Response (Success) +[JSON example] + +## Response (Errors) +[Table + JSON examples per error code] + +## Downstream Services +[Table of config keys, URLs, methods] +``` diff --git a/.agents/skills/security-best-practices/SKILL.md b/.agents/skills/security-best-practices/SKILL.md new file mode 100644 index 0000000..871c0d5 --- /dev/null +++ b/.agents/skills/security-best-practices/SKILL.md @@ -0,0 +1,152 @@ +--- +name: security-best-practices +description: Security review for banking APIs — headers, input validation, log masking, and trace integrity. +source: community + V4 banking patterns (pinned 2026-03-19) +--- + +# Security Best Practices for Banking APIs + +## Overview +Review and enforce security practices in API implementations, with focus on banking-grade requirements: input validation, header sanitization, log masking, and trace integrity. + +## When to Use +- Reviewing header handling in Resources and Adapters +- Validating input sanitization on DTOs +- Auditing log filters for sensitive data exposure +- Verifying trace integrity (SecurityTracePort) +- Pre-delivery security review + +## Instructions + +### 1. Input Validation + +**Every input field MUST have explicit validation:** + +```java +// ✅ Correct — validation codes tied to error catalog +@NotNull(message = "VDE01") +@Valid +private CustomerReference customerReference; + +// ✅ Correct — pattern restricts to known values +@NotNull(message = "VDE01") +@Pattern(regexp = "^[VEJPGCR]$", message = "VDE02") +private String customerIdType; + +// ❌ Incorrect — no validation +private String customerIdType; + +// ❌ Incorrect — validation without error code +@NotNull +private String customerId; +``` + +**Checklist:** +- [ ] All required fields have `@NotNull(message = "VDE01")` +- [ ] Enum-like fields have `@Pattern` with `message = "VDE02"` +- [ ] Nested objects have `@Valid` to cascade validation +- [ ] `ValidationExceptionMapper` is present and registered as `@Provider` + +### 2. Header Security + +**Required headers MUST be validated:** + +```java +// ✅ Correct — declared as required with description +@Parameter(description = "Application ID", required = true) +@HeaderParam("appId") String appId, + +// The MdcLoggingFilter handles null → "UNKNOWN_APP" fallback +// But the Resource should still declare them as required +``` + +**Headers that MUST NOT be logged without masking:** +- `authorization` +- `cookie` +- `x-api-key` +- Any custom credentials header + +**Implementation in `RestClientLoggingFilter`:** +```java +private static final Set SENSITIVE_HEADERS = + Set.of("authorization", "cookie", "x-api-key"); + +// Mask: "authorization=[PROTECTED]" +``` + +### 3. Log Masking + +**PII and sensitive data MUST be masked in production logs:** + +| Data Type | Log Level Allowed | Masking Rule | +|---|---|---| +| `customerId` | DEBUG only | Never in INFO | +| `customerIdType` | DEBUG only | Never in INFO | +| `deviceIp` | INFO | OK — used for fraud detection | +| `traceId` / `deviceSessionReference` | INFO | OK — correlation ID | +| `appId` | INFO | OK — non-sensitive identifier | +| Authorization headers | NEVER | `[PROTECTED]` | + +**Rule:** In `%prod` profile, only `com.banesco` level INFO. Never expose PII at INFO level. + +### 4. Trace Integrity + +**The SecurityTracePort MUST:** +- Execute in `finally` block — ALWAYS, even if the main logic throws +- Use `AsyncMdcRunner` to preserve MDC context in the async thread +- Never block the main response thread +- Handle its own exceptions silently (log ERROR, don't propagate) + +**Checklist:** +- [ ] `writeTrace()` called in `finally` with `asyncRunner.run()` +- [ ] `traceId` read from `RequestContext.getRequestId()`, not hardcoded +- [ ] If `traceId` is null, fallback to `"UNKNOWN"` (not empty string) +- [ ] `inputData` and `outputData` serialized with `ObjectMapper` (not `.toString()`) +- [ ] Trace failure logged as ERROR but NEVER propagated to caller + +### 5. ConfigMap Security + +**Environment variables for URLs MUST use the pattern:** +```yaml +url: ${INTEGRATION__URL:} +``` + +- Production URLs NEVER hardcoded in `application.yml` +- Dev URLs can be hardcoded as defaults for convenience +- Credentials NEVER in `application.yml` — use Kubernetes Secrets + +### 6. HTTP Security Headers + +**Response headers to consider:** +- `traceId` in response (for client correlation) — ✅ implemented in `MdcLoggingFilter` +- `Content-Type: application/json` — ✅ automatic with JAX-RS +- `X-Content-Type-Options: nosniff` — add if exposed to browser clients +- `Cache-Control: no-store` — banking APIs MUST NOT be cached + +### 7. Security Review Output Format + +```markdown +## Security Review — + +### Input Validation +- [ ] All fields validated with error codes +- [ ] @Pattern on constrained fields + +### Header Security +- [ ] Sensitive headers masked in logs +- [ ] Required headers declared in Resource + +### Log Masking +- [ ] No PII at INFO level in prod +- [ ] SENSITIVE_HEADERS set includes all credential headers + +### Trace Integrity +- [ ] SecurityTracePort in finally with AsyncMdcRunner +- [ ] TraceId not null/empty + +### ConfigMap +- [ ] No hardcoded prod URLs +- [ ] No credentials in application.yml + +### Overall Risk: LOW | MEDIUM | HIGH +``` diff --git a/.agents/skills/systematic-debugging/SKILL.md b/.agents/skills/systematic-debugging/SKILL.md new file mode 100644 index 0000000..5803756 --- /dev/null +++ b/.agents/skills/systematic-debugging/SKILL.md @@ -0,0 +1,131 @@ +--- +name: systematic-debugging +description: Four-phase debugging methodology. Always find root cause before attempting fixes. +source: obra/superpowers (pinned 2026-03-19) +--- + +# Systematic Debugging + +## Overview +Random fixes waste time and create new bugs. Quick patches mask underlying issues. + +**Core principle:** ALWAYS find root cause before attempting fixes. Symptom fixes are failure. + +## The Iron Law +``` +NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST +``` + +If you haven't completed Phase 1, you cannot propose fixes. + +## When to Use +Use for ANY technical issue: +- Test failures +- Bugs in production +- Unexpected behavior +- Performance problems +- Build failures +- Integration issues + +**Use this ESPECIALLY when:** +- Under time pressure (emergencies make guessing tempting) +- "Just one quick fix" seems obvious +- You've already tried multiple fixes +- Previous fix didn't work +- You don't fully understand the issue + +## The Four Phases +You MUST complete each phase before proceeding to the next. + +### Phase 1: Root Cause Investigation +**BEFORE attempting ANY fix:** + +1. **Read Error Messages Carefully** + - Don't skip past errors or warnings + - They often contain the exact solution + - Read stack traces completely + - Note line numbers, file paths, error codes + +2. **Reproduce Consistently** + - Can you trigger it reliably? + - What are the exact steps? + - Does it happen every time? + - If not reproducible → gather more data, don't guess + +3. **Check Recent Changes** + - What changed that could cause this? + - Git diff, recent commits + - New dependencies, config changes + - Environmental differences + +4. **Gather Evidence in Multi-Component Systems** + For EACH component boundary: + - Log what data enters component + - Log what data exits component + - Verify environment/config propagation + - Check state at each layer + Run once to gather evidence showing WHERE it breaks. + +5. **Trace Data Flow** + - Where does bad value originate? + - What called this with bad value? + - Keep tracing up until you find the source + - Fix at source, not at symptom + +### Phase 2: Pattern Analysis +**Find the pattern before fixing:** + +1. **Find Working Examples** — Locate similar working code in same codebase +2. **Compare Against References** — Read reference implementation COMPLETELY +3. **Identify Differences** — List every difference, however small +4. **Understand Dependencies** — Settings, config, environment, assumptions + +### Phase 3: Hypothesis and Testing +**Scientific method:** + +1. **Form Single Hypothesis** — "I think X is the root cause because Y" +2. **Test Minimally** — Make the SMALLEST possible change to test +3. **Verify Before Continuing** — Did it work? Yes → Phase 4. No → NEW hypothesis +4. **When You Don't Know** — Say "I don't understand X". Don't pretend. + +### Phase 4: Implementation +**Fix the root cause, not the symptom:** + +1. **Create Failing Test Case** — Simplest possible reproduction +2. **Implement Single Fix** — ONE change at a time, no "while I'm here" improvements +3. **Verify Fix** — Test passes? No other tests broken? Issue resolved? +4. **If Fix Doesn't Work** — If < 3 attempts: return to Phase 1. If ≥ 3: STOP and question the architecture +5. **If 3+ Fixes Failed: Question Architecture** — Is this pattern fundamentally sound? Discuss with human before more fixes. + +## Red Flags - STOP and Follow Process +- "Quick fix for now, investigate later" +- "Just try changing X and see if it works" +- "Add multiple changes, run tests" +- "It's probably X, let me fix that" +- "I don't fully understand but this might work" +- Each fix reveals new problem in different place + +**ALL of these mean: STOP. Return to Phase 1.** + +## Common Rationalizations +| Excuse | Reality | +|--------|---------| +| "Issue is simple, don't need process" | Simple issues have root causes too. Process is fast for simple bugs. | +| "Emergency, no time for process" | Systematic debugging is FASTER than guess-and-check thrashing. | +| "Just try this first" | First fix sets the pattern. Do it right from the start. | +| "Multiple fixes at once saves time" | Can't isolate what worked. Causes new bugs. | +| "I see the problem, let me fix it" | Seeing symptoms ≠ understanding root cause. | + +## Quick Reference +| Phase | Key Activities | Success Criteria | +|-------|---------------|------------------| +| **1. Root Cause** | Read errors, reproduce, check changes, gather evidence | Understand WHAT and WHY | +| **2. Pattern** | Find working examples, compare | Identify differences | +| **3. Hypothesis** | Form theory, test minimally | Confirmed or new hypothesis | +| **4. Implementation** | Create test, fix, verify | Bug resolved, tests pass | + +## Real-World Impact +- Systematic approach: 15-30 minutes to fix +- Random fixes approach: 2-3 hours of thrashing +- First-time fix rate: 95% vs 40% +- New bugs introduced: Near zero vs common diff --git a/.agents/skills/test-driven-development/SKILL.md b/.agents/skills/test-driven-development/SKILL.md new file mode 100644 index 0000000..834badf --- /dev/null +++ b/.agents/skills/test-driven-development/SKILL.md @@ -0,0 +1,166 @@ +--- +name: test-driven-development +description: Write the test first. Watch it fail. Write minimal code to pass. Enforces TDD discipline. +source: obra/superpowers (pinned 2026-03-19) +--- + +# Test-Driven Development (TDD) + +## Overview +Write the test first. Watch it fail. Write minimal code to pass. + +**Core principle:** If you didn't watch the test fail, you don't know if it tests the right thing. + +**Violating the letter of the rules is violating the spirit of the rules.** + +## When to Use +**Always:** +- New features +- Bug fixes +- Refactoring +- Behavior changes + +**Exceptions (ask your human partner):** +- Throwaway prototypes +- Generated code +- Configuration files + +Thinking "skip TDD just this once"? Stop. That's rationalization. + +## The Iron Law +``` +NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST +``` + +Write code before the test? Delete it. Start over. + +**No exceptions:** +- Don't keep it as "reference" +- Don't "adapt" it while writing tests +- Don't look at it +- Delete means delete + +Implement fresh from tests. Period. + +## Red-Green-Refactor + +### RED - Write Failing Test +Write one minimal test showing what should happen. + +**Requirements:** +- One behavior +- Clear name +- Real code (no mocks unless unavoidable) + +### Verify RED - Watch It Fail +**MANDATORY. Never skip.** + +Confirm: +- Test fails (not errors) +- Failure message is expected +- Fails because feature missing (not typos) + +**Test passes?** You're testing existing behavior. Fix test. + +**Test errors?** Fix error, re-run until it fails correctly. + +### GREEN - Minimal Code +Write simplest code to pass the test. + +Don't add features, refactor other code, or "improve" beyond the test. + +### Verify GREEN - Watch It Pass +**MANDATORY.** + +Confirm: +- Test passes +- Other tests still pass +- Output pristine (no errors, warnings) + +**Test fails?** Fix code, not test. +**Other tests fail?** Fix now. + +### REFACTOR - Clean Up +After green only: +- Remove duplication +- Improve names +- Extract helpers + +Keep tests green. Don't add behavior. + +### Repeat +Next failing test for next feature. + +## Good Tests +| Quality | Good | Bad | +|---------|------|-----| +| **Minimal** | One thing. "and" in name? Split it. | `test('validates email and domain and whitespace')` | +| **Clear** | Name describes behavior | `test('test1')` | +| **Shows intent** | Demonstrates desired API | Obscures what code should do | + +## Why Order Matters +Tests written after code pass immediately. Passing immediately proves nothing: +- Might test wrong thing +- Might test implementation, not behavior +- Might miss edge cases you forgot +- You never saw it catch the bug + +Test-first forces you to see the test fail, proving it actually tests something. + +## Common Rationalizations +| Excuse | Reality | +|--------|---------| +| "Too simple to test" | Simple code breaks. Test takes 30 seconds. | +| "I'll test after" | Tests passing immediately prove nothing. | +| "Tests after achieve same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" | +| "Already manually tested" | Ad-hoc ≠ systematic. No record, can't re-run. | +| "Deleting X hours is wasteful" | Sunk cost fallacy. Keeping unverified code is technical debt. | +| "Need to explore first" | Fine. Throw away exploration, start with TDD. | +| "Test hard = design unclear" | Listen to test. Hard to test = hard to use. | +| "TDD will slow me down" | TDD faster than debugging. | + +## Red Flags - STOP and Start Over +- Code before test +- Test after implementation +- Test passes immediately +- Can't explain why test failed +- Tests added "later" +- Rationalizing "just this once" +- "I already manually tested it" + +**All of these mean: Delete code. Start over with TDD.** + +## Verification Checklist +Before marking work complete: + +- [ ] Every new function/method has a test +- [ ] Watched each test fail before implementing +- [ ] Each test failed for expected reason (feature missing, not typo) +- [ ] Wrote minimal code to pass each test +- [ ] All tests pass +- [ ] Output pristine (no errors, warnings) +- [ ] Tests use real code (mocks only if unavoidable) +- [ ] Edge cases and errors covered + +Can't check all boxes? You skipped TDD. Start over. + +## When Stuck +| Problem | Solution | +|---------|----------| +| Don't know how to test | Write wished-for API. Write assertion first. | +| Test too complicated | Design too complicated. Simplify interface. | +| Must mock everything | Code too coupled. Use dependency injection. | +| Test setup huge | Extract helpers. Still complex? Simplify design. | + +## Debugging Integration +Bug found? Write failing test reproducing it. Follow TDD cycle. Test proves fix and prevents regression. + +Never fix bugs without a test. + +## Final Rule +``` +Production code → test exists and failed first +Otherwise → not TDD +``` + +No exceptions without your human partner's permission. diff --git a/.gentle/context/business-rules.md b/.gentle/context/business-rules.md new file mode 100644 index 0000000..11278cf --- /dev/null +++ b/.gentle/context/business-rules.md @@ -0,0 +1,11 @@ +# Contexto del Negocio: Internet Banking Seguro + +## Objetivo +Plataforma web de banca por internet para que los clientes gestionen sus finanzas, cuentas y transferencias de forma ágil, transparente y ultra-segura. + +## Reglas de Negocio +- **Cuentas Soportadas:** Cada usuario puede poseer múltiples cuentas (Corriente, Ahorros y Tarjeta de Crédito, en otras monedas). +- **Límites de Transferencia:** Monto máximo diario de transferencia de $5,000 USD (o equivalente) a terceros. Las transferencias entre cuentas propias no tienen límite. +- **Seguridad y Sesión:** Autocierre de sesión (auto-logout) tras 5 minutos de inactividad del cliente. Encriptación obligatoria para cualquier visualización de saldos o números de cuenta completos en el cliente. +- **Auditoría Financiera:** Todo movimiento de dinero, intento de login (exitoso o fallido) y cambio de credenciales debe generar un registro de log inmutable en el servidor. +- **Cifrado Extremo a Extremo (End-to-End Encryption - E2EE):** Toda la información altamente confidencial en tránsito y en reposo (credenciales, números de cuenta, saldos, importes de transferencias y tokens de sesión) debe estar encriptada de extremo a extremo (E2EE) desde el navegador del cliente hasta el servidor del backend (usando Kong Gateway y encriptación robusta a nivel de aplicación). Esto asegura inmunidad absoluta contra cualquier tipo de intermediarios o fugas en tránsito, garantizando un estándar de seguridad de grado bancario. diff --git a/.gentle/context/context-app.md b/.gentle/context/context-app.md new file mode 100644 index 0000000..68e522d --- /dev/null +++ b/.gentle/context/context-app.md @@ -0,0 +1,449 @@ +# Internet Banking - Aplicación Web Segura + +Aplicación web de Internet Banking construida con **Next.js 14 (App Router)**, **TypeScript**, **TailwindCSS + daisyUI**, y **Zustand** para gestión de estado. El backend está desarrollado en **Java 25 Spring Boot** y protegido por **Kong Gateway**. + +## 🚀 Características + +- ✅ **Autenticación segura** con tokens JWT en cookies HTTP-only +- ✅ **Server Components** de Next.js para máximo rendimiento +- ✅ **Middleware de autenticación** server-side +- ✅ **Sistema de logs** centralizado (escribe en archivo .txt) +- ✅ **Encriptación Kong** para datos sensibles +- ✅ **UI moderna** con TailwindCSS y daisyUI +- ✅ **TypeScript** para type-safety completo +- ✅ **Zustand** para estado cliente (no Redux) +- ✅ **Sin useEffect/useContext** innecesarios (server-first) +# Internet Banking (Next.js) + +This repository contains a Next.js application scaffolded with `create-next-app`. + +## Getting started + +1. Install dependencies: + +```bash +npm install +``` + +2. Run the development server: + +```bash +npm run dev +# then open http://localhost:3000 +``` + +## Requisitos + +- Node.js 18 LTS o superior + +## Instalación y ejecución + +1. Instala las dependencias: + +```bash +npm install +``` + +2. Ejecuta el servidor de desarrollo: + +```bash +npm run dev +# luego abre http://localhost:3000 +``` + +## Dependencias + +Las dependencias actuales (según `package.json`): + +### Runtime + +- `next` 15.5.6 +- `react` 19.1.0 +- `react-dom` 19.1.0 +- `daisyui` 5.4.5 +- `react-icons` 5.5.0 +- `zustand` 5.0.8 + +### Desarrollo + +- `typescript` 5 +- `@types/node` 20 +- `@types/react` 19 +- `@types/react-dom` 19 +- `eslint` 9 +- `@eslint/eslintrc` 3 +- `eslint-config-next` 15.5.6 +- `tailwindcss` 4.1.17 +- `@tailwindcss/postcss` 4.1.17 + +## Notas + +- Para ejecutar el linter localmente: + +```bash +npm run lint +``` + +## 🤖 Infraestructura de Ingeniería AI-Native (Agentes y Esquema MCP) + +Esta aplicación está diseñada desde sus cimientos para el desarrollo asistido por **Agentes de Inteligencia Artificial Autónomos** mediante el protocolo **MCP (Model Context Protocol)**, asegurando consistencia arquitectónica, memoria persistente entre sesiones y navegación contextual ultra-rápida. + +### 1. El Esquema de Servidores MCP (mcp_config.json) + +Para iniciar el entorno de desarrollo con soporte de IA y permitir que los agentes se auto-direccionen, debes registrar los siguientes servidores en el archivo de configuración global de tu entorno de ejecución (ej. `~/.gemini/antigravity/mcp_config.json`): + +```json +{ + "mcpServers": { + "engram": { + "command": "engram", + "args": [ + "mcp", + "--tools=agent" + ] + }, + "graphify": { + "command": "d:\\Jess\\agent\\graphify\\.venv\\Scripts\\python.exe", + "args": [ + "-m", + "graphify.serve", + "d:/Jess/agent/frontend-ai/graphify-out/graph.json" + ] + } + } +} +``` + +* **Engram (Memoria Persistente)**: Servidor escrito en Go que expone herramientas para almacenar decisiones, resúmenes de sesión (`mem_save`) y recuperar contexto de sesiones previas (`mem_search`, `mem_context`), evitando la pérdida de contexto sobre las reglas de negocio críticas o decisiones pasadas. +* **Graphify (Grafo del Repositorio)**: Servidor que mapea todo el código, layouts de Next.js, API routes y documentación en un grafo semántico. Permite al agente responder preguntas de arquitectura mediante consultas directas en lugar de hacer lecturas completas de archivos, optimizando drásticamente la ventana de contexto. + +--- + +### 2. Reglas de Comportamiento para Agentes de IA (AGENTS.md / CLAUDE.md) + +Cualquier agente que trabaje en esta base de código está **estrictamente obligado** a seguir las siguientes directrices y reglas operativas integradas en el proyecto: + +#### 🔐 Seguridad y Autenticación Primero +1. **Nunca escribirás claves o credenciales en texto plano**: El agente tiene estrictamente prohibido commitear archivos `.env` o variables con valores reales. Siempre utilizará variables de entorno. +2. **Respeto absoluto por el Middleware Server-Side**: Para proteger cualquier ruta o recurso, el agente DEBE usar el middleware centralizado `serverRequireAuth` desde `lib/auth/middleware.ts` en los Server Components. Bajo ninguna circunstancia omitirá este paso o creará validaciones ad-hoc. +3. **Cookies HTTP-Only y Secure**: Los tokens JWT nunca deben tocar el `localStorage` o `sessionStorage` del cliente. Si el agente diseña flujos de autenticación en el cliente, debe delegar el almacenamiento y la gestión de la cookie al navegador y al backend. +4. **Encriptación de Datos Sensibles**: Cualquier dato altamente confidencial (ej. números de cuenta, saldos, datos personales) que viaje por el cliente debe encriptarse usando el módulo placeholder de Kong Gateway (`lib/cypher/encrypt.ts`). + +#### 📝 Sistema de Logs Centralizado +* El agente **debe loguear activamente** todas las acciones críticas (inicios de sesión, accesos denegados, errores de comunicación con el backend, llamadas a la API) usando los módulos `server-logger` y `client-logger`. +* Todos los logs generados en componentes del cliente **deben enrutarse** hacia la API local `POST /api/logs` para asegurar que queden guardados en el archivo centralizado `logs/app.log`. + +#### 🏗️ Desarrollo Incremental y Verificabilidad +* El agente debe mantener el archivo `STATE.md` y `ENGRAM.md` actualizados en cada punto de control (Checkpoint) para evitar la degradación de la memoria y la ventana de contexto del modelo. +* Después de realizar cualquier cambio estructural en el código, el agente ejecutará localmente `graphify update .` para asegurar que el grafo de conocimiento del proyecto refleje los nuevos módulos inmediatamente. + +## 🏗️ Estructura del Proyecto + +``` +internet-banking/ +├── app/ # Next.js App Router +│ ├── page.tsx # Página principal +│ ├── layout.tsx # Layout principal +│ ├── ClientAuthProvider.tsx # Provider para hidratación de auth +│ ├── globals.css # Estilos globales +│ ├── about/ # Sección "Acerca de" +│ │ ├── page.tsx +│ │ ├── layout.tsx +│ │ ├── components/ +│ │ │ ├── aboutHeader.tsx +│ │ │ └── aboutContent.tsx +│ │ ├── service/ +│ │ │ └── fetchAbout.ts +│ │ └── hooks/ +│ │ └── useAboutData.ts +│ ├── login/ # Página de login +│ │ ├── page.tsx +│ │ └── LoginForm.tsx +│ ├── dashboard/ # Dashboard protegido +│ │ └── page.tsx +│ ├── model/ # Modelos TypeScript +│ │ └── cuenta.ts +│ └── api/ # API Routes +│ ├── logs/ +│ │ └── route.ts # POST /api/logs +│ └── auth/ +│ ├── me/ +│ │ └── route.ts # GET /api/auth/me +│ └── logout/ +│ └── route.ts # POST /api/auth/logout +├── components/ +│ └── ui/ # Componentes UI reutilizables +│ ├── button.tsx +│ ├── input.tsx +│ ├── header.tsx +│ └── table.tsx +├── lib/ +│ ├── auth/ # Autenticación +│ │ ├── middleware.ts # Middleware server-side +│ │ └── client/ +│ │ └── useAuthStore.ts # Zustand store +│ ├── logger/ # Sistema de logs +│ │ ├── server-logger.ts # Logger server-side +│ │ └── client-logger.ts # Logger client-side +│ └── cypher/ # Encriptación Kong +│ ├── encrypt.ts +│ └── decrypt.ts +├── logs/ +│ └── app.log # Archivo de logs (no en git) +├── middleware.ts # Next.js Edge Middleware +├── package.json +├── tsconfig.json +├── tailwind.config.ts +├── next.config.js +└── README.md +``` + +## 🔐 Autenticación + +### Flujo de Autenticación + +1. **Login**: Usuario envía credenciales a `POST /api/auth/login` +2. **Backend**: Spring Boot valida y devuelve tokens en cookies HTTP-only: + - `access_token`: Token de acceso (corta duración) + - `refresh_token`: Token de refresco (larga duración) +3. **Frontend**: Cookies se establecen automáticamente (HTTP-only, Secure, SameSite=strict) +4. **Validación**: Cada petición a rutas protegidas valida el token server-side +5. **Logout**: `POST /api/auth/logout` limpia cookies + +### Middleware de Autenticación + +#### Server-Side (lib/auth/middleware.ts) + +```typescript +// Proteger una página (Server Component) +import { serverRequireAuth } from '@/lib/auth/middleware'; + +export default async function ProtectedPage() { + const user = await serverRequireAuth(); // Redirige si no autenticado + return
Hola {user.name}
; +} + +// Check opcional (no redirige) +import { checkAuth } from '@/lib/auth/middleware'; + +const authResult = await checkAuth(); +if (authResult.isAuthenticated) { + // Usuario logueado +} +``` + +#### Edge Middleware (middleware.ts) + +Automáticamente redirige rutas protegidas (`/dashboard`, `/profile`, etc.) si no hay token. + +### Zustand Store (Client-Side) + +```typescript +'use client'; +import { useAuthStore } from '@/lib/auth/client/useAuthStore'; + +function MyComponent() { + const { user, isAuthenticated, logout } = useAuthStore(); + + return ( +
+ {isAuthenticated &&

Hola {user?.name}

} + +
+ ); +} +``` + +**IMPORTANTE**: El store Zustand NO guarda tokens, solo datos del usuario y flags UI. + +## 📝 Sistema de Logs + +Todos los logs se escriben server-side en `logs/app.log`. + +### Desde Server Components / API Routes + +```typescript +import { logInfo, logWarn, logError } from '@/lib/logger/server-logger'; + +logInfo('User logged in', { userId: '123' }); +logWarn('Failed login attempt', { email: 'user@example.com' }); +logError('Database connection failed', { error: err.message }); +``` + +### Desde Client Components + +```typescript +'use client'; +import { logInfo, logWarn, logError } from '@/lib/logger/client-logger'; + +// Estos envían logs a /api/logs que los escribe server-side +logInfo('Button clicked', { action: 'submit' }); +logError('Form validation failed', { field: 'email' }); +``` + +### Formato de Logs + +``` +[2024-11-07T10:30:00.000Z] [INFO] Login success | {"userId":"123","email":"user@example.com"} +[2024-11-07T10:31:00.000Z] [WARN] Unauthorized access attempt | {"path":"/dashboard"} +[2024-11-07T10:32:00.000Z] [ERROR] Backend connection failed | {"error":"ECONNREFUSED"} +``` + +## 🔒 Seguridad + +### Tokens HTTP-Only + +- Los tokens JWT **nunca** se almacenan en `localStorage` o `sessionStorage` +- Se usan cookies **HTTP-only**, **Secure** (en producción), **SameSite=strict** +- No accesibles desde JavaScript del cliente + +### Encriptación Kong + +Para datos sensibles que necesitan encriptación: + +```typescript +import { kongEncrypt, kongDecrypt } from '@/lib/cypher/decrypt'; + +// Encriptar +const encrypted = kongEncrypt('sensitive-data'); + +// Desencriptar +const decrypted = kongDecrypt(encrypted); + +// TODO: Reemplazar con la librería Kong real una vez proporcionada +``` + +### CORS y CSRF + +Asegúrate de configurar en tu backend Spring Boot: + +```java +// Permitir solo orígenes aprobados +@CrossOrigin(origins = "http://localhost:3000", allowCredentials = "true") + +// SameSite=strict para cookies +cookie.setSameSite("strict"); +``` + +## 🧪 Pruebas Manuales + +### 1. Login Exitoso + +1. Ir a `/login` +2. Ingresar credenciales válidas +3. **Esperado**: Redirige a `/dashboard` +4. **Log**: `[INFO] Login success | {"userId":"123"}` + +### 2. Login Fallido + +1. Ir a `/login` +2. Ingresar credenciales inválidas +3. **Esperado**: Muestra mensaje de error +4. **Log**: `[WARN] Login failed | {"email":"us***@example.com"}` + +### 3. Acceso No Autorizado + +1. Sin estar logueado, intentar acceder a `/dashboard` +2. **Esperado**: Redirige a `/login?redirect=/dashboard` +3. **Log**: `[WARN] Unauthorized access attempt | {"redirectTo":"/login"}` + +### 4. Logout + +1. Estando logueado, hacer click en "Cerrar Sesión" +2. **Esperado**: Cookies eliminadas, redirige a `/login` +3. **Log**: `[INFO] Logout user: 123` + +## 📦 Build para Producción + +```bash +# Build +npm run build + +# Start production server +npm run start +``` + +### Variables de Entorno en Producción + +Asegúrate de configurar: + +```env +NODE_ENV=production +NEXT_PUBLIC_API_URL=https://api.tudominio.com/api +API_URL_SERVER=https://api-internal.tudominio.com/api +KONG_SECRET_KEY= +``` + +## 🚨 Solución de Problemas + +### Error: "Failed to fetch" + +- Verifica que el backend esté corriendo +- Verifica las URLs en `.env.local` +- Revisa los logs en `logs/app.log` + +### Error: "Unauthorized" + +- Verifica que las cookies se estén estableciendo correctamente +- Revisa la configuración CORS del backend +- Asegúrate que `withCredentials: true` esté en las peticiones fetch + +### Error: Cookies no se establecen + +- En desarrollo: Asegúrate que frontend y backend estén en el mismo dominio (localhost) +- Verifica configuración `SameSite` en backend +- Revisa que `httpOnly: true` esté configurado correctamente + +### Logs no se escriben + +- Verifica que `ENABLE_SERVER_LOGS=true` +- Asegúrate que la carpeta `logs/` tenga permisos de escritura +- Revisa los logs de consola para errores + +## 📚 Documentación Adicional + +- [Next.js 14 Documentation](https://nextjs.org/docs) +- [TailwindCSS](https://tailwindcss.com/docs) +- [daisyUI Components](https://daisyui.com/components/) +- [Zustand](https://docs.pmnd.rs/zustand/getting-started/introduction) +- [Kong Gateway](https://docs.konghq.com/) + +## 🔧 Scripts Disponibles + +```bash +npm run dev # Desarrollo +npm run build # Build producción +npm run start # Servidor producción +npm run lint # ESLint +npm run type-check # TypeScript type checking +``` + +## 📝 TODOs Pendientes + +Los siguientes TODOs están marcados en el código con `/* TODO */`: + +1. **lib/cypher/encrypt.ts y decrypt.ts**: Reemplazar implementación placeholder con librería Kong real +2. **lib/auth/middleware.ts**: Ajustar headers según requerimientos del backend +3. **app/api/auth/me/route.ts**: Ajustar headers según backend +4. **app/login/LoginForm.tsx**: Ajustar payload y endpoint de login según backend +5. **Variables de entorno**: Reemplazar valores de ejemplo con valores reales +6. **Endpoints backend**: Verificar que coincidan con los del backend Spring Boot + +## 🤝 Contribución + +1. Crear una rama: `git checkout -b feature/nueva-funcionalidad` +2. Commit cambios: `git commit -am 'Agrega nueva funcionalidad'` +3. Push a la rama: `git push origin feature/nueva-funcionalidad` +4. Crear Pull Request + +## 📄 Licencia + +Este proyecto es privado y confidencial. + +## 👥 Equipo + +Desarrollado para el sistema de Internet Banking. + +--- + +**Nota de Seguridad**: Nunca commitear archivos con claves reales, tokens, o credenciales. Usar siempre variables de entorno y mantener `.env.local` fuera del control de versiones. \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2e99c0b..d6608a7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,13 @@ node_modules .next .env.local .env.local.template -.gentle -.agents .git .cursor .vscode .claude +.gemini +.agent +.openai +.ollama