27 KiB
27 KiB
Historial (append-only)
Añadir entradas al final. No reescribir historial previo.
2026-08-14 — F-001 Scaffold modular monolith skeleton — DONE
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, verify.sh exit 0
- Entregable: skeleton TypeScript + Fastify en project/ con boundary checker testeado; specs/F-001-scaffold completos; spec/tech.md con justificación de dependencias
- Artefactos: work/artifacts/F-001/ (architect.md, implementer.md, reviewer.json, security.json, qa.json, documenter.md, leader-close.json)
- Nota: el boundary checker detectó una violación real durante build (test escapando del módulo) y se corrigió moviendo los tests de composición a src/app
2026-08-14 — F-002 Database foundation with module-owned schemas — DONE
- Gates: reviewer APPROVED, security APPROVED (con ronda de hardening), qa APPROVED, verify.sh exit 0
- Entregable: migraciones node-pg-migrate (up/down/no-op probados contra PostgreSQL 16 real), pool fail-fast, docker-compose (Postgres + Redis), convención _ documentada
- Nota: security devolvió un hallazgo bajo (interpolación de identificador en DDL de tests); se mitigó con validación estricta + tests de regresión
- Artefactos: work/artifacts/F-002/
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, verify.sh exit 0
- Entregable: request_id (generado o propagado-sanitizado), logs JSON correlacionados, error envelope v2 con requestId, hook de validación parseJson (zod), server con logging inyectable
- Nota: doc stage rebotó a build para escribir README (project/ está gateado a build/implementer/running); comportamiento correcto del guardrail
- Artefactos: work/artifacts/F-003/
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, verify.sh exit 0
- Entregable: loadConfig fail-fast (DATABASE_URL requerido, errores solo con nombres de variables), módulo flags tras FeatureFlagProvider (default OFF, flip en runtime sin redeploy), app.flags decorado
- Nota: los tests detectaron un bug real en build (case-normalization del store); corregido antes de gates con test de regresión
- Cero dependencias nuevas
- Artefactos: work/artifacts/F-004/
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, verify.sh exit 0
- Entregable: módulo identity hexagonal (domain/application/infrastructure/api), migración 002 reversible, argon2id OWASP tras puerto PasswordHasher, sesiones opacas (solo SHA-256 del token en DB), cookie HttpOnly+Secure+SameSite=Lax, rate limit 10 fallos -> 429 + Retry-After tras interfaz, 401 idéntico anti-enumeración con timing igualado
- Nota: review detectó falta de tests para COOKIE_SECURE; fix aplicado antes de aprobar el gate. Suite de migraciones F-002 actualizada a rollback completo (count:0) por tener ahora 2 migraciones
- Deps nuevas: argon2, @fastify/cookie (justificadas en spec/tech.md)
- Artefactos: work/artifacts/F-005/
- Users module: profile + address CRUD (users_profiles, users_addresses, migration 004); roles on identity_users (migration 003)
- RBAC: owner-or-admin via shared/auth.ts injected from composition root; authz before existence checks; SQL scoped by user_id
- Identity: session-authenticator export + role in model/responses; @fastify/cookie moved to app root
- Zero new dependencies; tests: unit 52 + integration 22; live smoke covered 401/403/200 paths; gates APPROVED
- Categories module: category tree with adjacency-list
parent_id, globally unique slugs, SEO title/description, migration 005 (categories_categories). - API: public
GET /categories/treeandGET /categoria/:slug; admin-only create/update/delete via shared auth injected at composition root. - Integrity: duplicate slug -> 409, self/descendant parent cycles -> 422, delete non-leaf -> 409; public URLs never require internal id.
- Zero new dependencies; tests: category unit tests green, integration acceptance tests present (skipped without TEST_DATABASE_URL); gates APPROVED.
- Artefactos: work/artifacts/F-007/
- Catalog module: product aggregate with states
draft,active,archived, unique slugs, SEO metadata, migration 006 (catalog_products,catalog_product_categories). - API: public active-only
GET /productos/:slugandGET /products/search; admin-only create/update via shared auth injected at composition root. - Integrity: duplicate slug -> 409, unknown category assignment -> 422; product-category assignment validates category ids without TypeScript imports from categories internals.
- Domain purity: catalog domain has zero database/HTTP imports; covered by test and boundary lint.
- Zero new dependencies; tests: catalog unit/domain tests green, integration acceptance tests present (skipped without TEST_DATABASE_URL); gates APPROVED.
- Artefactos: work/artifacts/F-008/
- Brands module: brand entity with globally unique slug, SEO metadata, migration 007 (
brands_brands). - Catalog integration: nullable
catalog_products.brand_id; product search supportsbrandSlugactive-only filter without TypeScript imports from brands internals. - API: public
GET /marca/:slug; admin-only brand create/update; duplicate brand slug -> 409. - Zero new dependencies; tests: product search unit green, brands/catalog integration acceptance tests present (skipped without TEST_DATABASE_URL); gates APPROVED.
- Artefactos: work/artifacts/F-009/
- Catalog variants:
catalog_product_variantswith globally unique SKU and optional unique EAN; admin create/update endpoints. - Rich data:
catalog_product_rich_datastores ingredients, allergens, nutrition, nutrition provenance, organic flag/certification. - Provenance: nutrition source required for every nutrition payload; manual nutrition blocks external-source overwrite in application use case.
- Scope kept tight: no OpenFoodFacts sync job, images, stock, or prices.
- Zero new dependencies; tests: rich-data unit green, catalog integration acceptance tests present (skipped without TEST_DATABASE_URL); gates APPROVED.
- Artefactos: work/artifacts/F-010/
- Added catalog-owned product/variant images with
catalog_product_images. - Added image metadata: URL, alt text, ordering position and role (
main/gallery). - Added storage boundary with local-first URL adapter; no CDN, upload or processing pipeline.
- Added admin attach/detach/reorder endpoints and public product image serialization.
- Gates: reviewer/security/qa APPROVED.
- Evidence: lint, typecheck, unit tests and verify green; integration tests remain skipped without
TEST_DATABASE_URL. - Split catalog search behind
ProductSearchRepository, separate from product CRUD persistence. - Added PostgreSQL FTS adapter over product, brand and category text.
- Added FTS migration indexes in
010_catalog_search_fts.js. - Search keeps active-only public behavior, brand filtering, pagination and stable ordering.
- Added structured
catalog_searchtelemetry with sanitized bounded query metadata and duration. - Gates: reviewer/security/qa APPROVED.
- Evidence: lint, typecheck, unit tests and verify green; integration tests remain skipped without
TEST_DATABASE_URL. - Added standalone Next.js storefront package under
project/storefront/. - Added App Router layout, navigation, footer and server-rendered home page.
- Added Tailwind CSS styling and frontend package scripts for lint/typecheck/build.
- Added typed public API client for backend catalog endpoints, guarded with
server-only. - Backend internals remain isolated; storefront does not import
project/src/**. - Gates: reviewer/security/qa APPROVED.
- Evidence: storefront lint/typecheck/build green; backend lint/typecheck/test green; verify green.
- Status: done.
- Added storefront product/category/brand/search catalog pages with ISR and metadata/OpenGraph.
- Added protected
POST /api/revalidatefor catalog paths. - Added backend
categorySlugfiltering for/products/search. - Gates approved: reviewer, security, QA.
- Final
./scripts/verify.sh: PASS. - Status: done.
- Added Organization, Product and BreadcrumbList JSON-LD to storefront pages.
- Added generated
sitemap.xmlandrobots.txt. - Added env-backed local 301 redirect store through Next proxy.
- Added public
GET /brandsfor sitemap brand URLs. - Gates approved: reviewer, security, QA.
- Final
./scripts/verify.sh: PASS. - Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: isolated inventory module with atomic stock operations, public InventoryService, PostgreSQL migration, API routes, and tests.
- Evidence: work/artifacts/F-016/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: server-side pricing with VAT, public PricingService, price history, API routes, migration, and tests.
- Evidence: work/artifacts/F-017/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: authenticated cart storing product/variant/quantity only, recalculating price and stock from services.
- Evidence: work/artifacts/F-018/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: server-side promotions with promo code validation and cart discount recalculation.
- Evidence: work/artifacts/F-019/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: server-side shipping zones/methods with free shipping threshold behind ShippingService.calculate.
- Evidence: work/artifacts/F-020/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: orders module with item snapshots and explicit state machine.
- Evidence: work/artifacts/F-021/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: orchestrator coordinating cart, pricing, promotions, inventory, shipping, orders and stub payment; idempotency_key prevents duplicate reservations.
- Evidence: work/artifacts/F-022/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: PaymentProvider interface with Stripe-style adapter; signed webhook with HMAC-SHA256 and 5-min tolerance; idempotent via unique constraint.
- Evidence: work/artifacts/F-023/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: notifications dispatch through EmailProvider port with idempotent event_id persistence.
- Evidence: work/artifacts/F-024/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: verified-purchase reviews with moderation, aggregate and one-review-per-order-item guarantee.
- Evidence: work/artifacts/F-025/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: simple CMS with slug routing and draft/publish states.
- Evidence: work/artifacts/F-026/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: read-through cache with explicit contracts; admin/metrics routes; loader fallback when adapter fails.
- Evidence: work/artifacts/F-027/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: rate limiter, audit log, admin MFA enrollment.
- Evidence: work/artifacts/F-028/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: tracer/meter abstraction, /ops/metrics route, checkout tracing span and business metrics.
- Evidence: work/artifacts/F-029/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: E2E checkout-flow test happy path + empty cart failure against real PostgreSQL.
- Evidence: work/artifacts/F-030/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: project/scripts/start-dev.sh levanta docker, migraciones y dev server.
- Evidence: work/artifacts/F-031/
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: start-dev.sh crea .env y usa npm run start.
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: start script ahora usa --env-file.
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: start-dev.sh exporta DATABASE_URL y NODE_ENV explicitamente.
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: project/CAVEMAN.md creado con arquitectura completa del proyecto.
- Verify: ./scripts/verify.sh passed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: Next.js homepage SSR con Hero, FeaturedProducts, CategoriesGrid, BrandsSection.
- Evidence: work/artifacts/F-036/
- Frontend dev: cd frontend && npx next dev
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: Script seed idempotente con 11 categorías, 6 marcas, 12 productos, precios, stock, shipping.
- Evidence: work/artifacts/F-037/
- Command: cd project && npm run db:seed
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: /categories listing + /categories/[slug] detail with SSR products.
- Evidence: work/artifacts/F-038/
- Backend: http://localhost:3000
- Frontend: http://localhost:3003
- Status: done
- Gates: reviewer APPROVED, security APPROVED, QA APPROVED
- Summary: /products listing + /products/[slug] SSR with pricing (€10.83/€8.95), stock, add-to-cart.
- Evidence: work/artifacts/F-039/
- Frontend: http://localhost:3003
- Gates: reviewer APPROVED, security APPROVED (upload remediation), QA APPROVED, verify.sh exit 0.
- Summary: consolidación de F-029/F-030 y FIX-11..FIX-19; migraciones 024-028 compatibles y reversibles; toolchains backend/admin/frontend/storefront verdes.
- Evidence: backend 124 unit tests + 56 integration tests; migration fresh up/no-op/down/up; builds Next verdes; 0 vulnerabilidades high en npm audit.
- Security:
/api/uploadrequiere sesión backoffice y valida tamaño, MIME, magic bytes y filename server-side. - Harness:
new_ticket.pyusa gate reviewer, soporta--startexclusivo y--normalize-gates. - Artefactos: work/artifacts/F-048/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: descripción editable de métodos de envío end-to-end. Migración 029 (
shipping_methods.description text); backend GET/POST/PATCH incluyendescription; nuevo endpoint públicoGET /shipping/methods?country=…&postalCode=…(read-only, filtra active=true); adminMethodFormcon input de descripción; storefrontCheckoutClientconsume el catálogo real y renderiza la descripción por método (array hardcodeado eliminado). - Security:
descriptionesz.string().max(500), plain text; write path requiere admin role (sin cambios); public GET es read-only y filtra SQL-level. - Tests: backend 124 passed, 56 skipped; typecheck green en frontend/admin/backend.
- Artefactos: work/artifacts/F-069/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: los atributos del producto (bio, vegano, sin-gluten, etc.) ahora aparecen como badges en la ficha de producto del frontend. Añadido
ProductAttributetipo +attributescampo a la interfazProduct; mapeo de labels en español (16 valores); componenteProductAttributescon badges accesibles; integrado tras el<h1>enproducts/[slug]/page.tsx. Backend ya devolvía atributos víaserializeProduct— sin cambios de backend. - Seguridad: cambio solo frontend, sin nuevas deps, sin endpoints, sin auth ni env vars;
attributeses read-only del API existente; el componente badge no usadangerouslySetInnerHTML. - Tests:
npx tsc --noEmitexit 0,npx eslinten 4 archivos exit 0,./scripts/verify.shexit 0. - Artefactos: work/artifacts/F-070/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: se añaden campos
emojiycolora las categorías end-to-end. Migración 030 (emoji VARCHAR(10),color TEXT, ambos nullable); backend domain/repository/routes actualizados; frontend CategoriesGrid y categories/page.tsx usan emoji/color almacenados con fallback a maps hardcoded; admin formulario con inputs de emoji+color y CategoryRow usacat.emoji ?? 📁; storefront pagina de categoría muestra el emoji. Backend rebuildado y reiniciado; PATCH /categories/:id con emoji+color verificado → HTTP 200. - Seguridad: 2 columnas nullable sin migración de datos; validación zod (emoji max 10, color max 200); color se renderiza como className (sin dangerouslySetInnerHTML).
- Tests: typecheck green en backend/frontend/admin/storefront; eslint exit 0; verify.sh exit 0.
- Artefactos: work/artifacts/F-071/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: PricingSection ahora carga dinámicamente los tipos impositivos activos desde GET /admin/tax-rates. Dropdown muestra las 3 tarifas activas (4%, 10%, 21%) en lugar de las 2 hardcodeadas. Cálculo de PVP usa el porcentaje dinámico. Backend soporta 'super-reduced' (tipo VatRate + CHECK constraint en BD). Migration 031 aplicada. API verificada: PUT con vatRate='super-reduced' → HTTP 200.
- Seguridad: valor adicional a CHECK constraint (aditivo, sin riesgo de datos); Zod valida en backend; tipos TypeScript extendidos (solo seguridad en compile-time).
- Tests: typecheck backend/admin exit 0; eslint exit 0; verify.sh exit 0.
- Artefactos: work/artifacts/F-072/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: Página de IVA (/tax-rates) ahora tiene un interruptor (pill toggle switch) en la columna Estado para activar/desactivar tipos directamente sin entrar en modo edición. Cambio solo frontend, sin cambios en backend ni BD.
- Tests: typecheck admin exit 0; eslint exit 0; verify.sh exit 0.
- Artefactos: work/artifacts/F-073/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: Página de auditoría (/audit) ahora tiene polling cada 5 segundos para mostrar nuevas entradas en tiempo real. Indicador "● En vivo" cuando polling activo. Badge "+N nuevas" cuando llegan entradas. El polling se detiene al filtrar o paginar.
- Tests: typecheck admin exit 0; eslint exit 0; verify.sh exit 0.
- Artefactos: work/artifacts/F-074/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: Inventario (/inventory) permite edición inline de SKU, EAN y Stock con click-to-edit. Añadido
productsApi.updateVariantal api-client. Columna "Acción" eliminada. - Tests: typecheck admin exit 0; eslint exit 0; verify.sh exit 0.
- Artefactos: work/artifacts/F-075/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: Productos (/products) tiene filtros por estado (Todos/Activos/Archivados) y columna "Tienda" con icono de enlace externo al frontend para productos activos.
- Tests: typecheck admin exit 0; eslint exit 0; verify.sh exit 0.
- Artefactos: work/artifacts/F-076/.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: La descripción breve en la lista de productos del admin ahora renderiza HTML de forma segura con sanitización (strips dangerous tags). Uso de
dangerouslySetInnerHTMLconrenderHtml(). - Tests: typecheck admin exit 0; eslint exit 0; verify.sh exit 0.
- Artefactos: work/artifacts/F-077/.
- Acción: Triage de incidencias reportadas por el operador. Se crearon 9 tickets detallados en
backlog/features.json:- F-079 [bug]
/productsno muestra la marca - F-080 [fix]
PVP (IVA incl.)en pestaña Precios bloquea edición de decimales - F-081 [fix]
PRECIO NETOen inventario: formato inconsistente y sin guardado - F-082 [fix]
/inventory: editables no se pueden guardar; UX de Stock debe ser click-to-edit sin lápiz - F-083 [feature]
/customers: password reset por enlace de email - F-084 [bug] Categorías padre no muestran emoji delante del nombre en la lista
- F-085 [fix]
/tax-rates: columnaTIPOno editable - F-086 [feature] Campo
fecha de caducidaden producto (backend + admin + listing + inventario) - F-087 [feature] Frontend: cap de cantidad al stock disponible (carrito y add-to-cart)
- F-079 [bug]
- Estado: todos en
pending. F-078 siguein_progress. Próximo paso:leaderarranca F-079 siguiendoone_feature_at_a_time. - verify.sh exit 0.
- Acción: cierre formal del backlog tras detectar inconsistencia entre
backlog/features.json(203 done) yscripts/verify.sh(FAIL). - Causa raíz: F-123..F-135 (13 features × 3 gates = 39 archivos) se cerraron con un esquema JSON de gates incorrecto — usaban
"reviewer": "<role>"en vez de"agent": "<role>". El checkobj.get('agent') != '<role>'enverify.shlos rechazaba, dejando el harness sin verificar. - Fix:
scripts/fix_gate_schema.py(nuevo, idempotente) copióagentdesde el campo legacyrevieweren los 39 archivos. Re-ejecución = no-op.stageno es obligatorio enverify.sh, no se tocó. runtime-status.jsonreseteado a idle conpython3 scripts/agent_status.py reset(feature_id null, stage idle, timeline vacía).work/current.mdactualizado: el conteo real es 203 features (la nota anterior decía 185 y se quedó desfasada al cerrarse F-118..F-135 sin actualizarcurrent.md).- Gates: n/a (cierre de harness, no feature nueva).
- verify.sh exit 0.
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, leader-close APPROVED, verify.sh exit 0
- Entregable: welcome email (account_created) on account creation (POST /auth/register) y order confirmation email on PaymentSucceeded (POST /payments/webhook). Best-effort (fire-and-forget dispatch en route handler + request.log.warn), idempotent (gate outcome.kind==='processed' evita duplicados), XSS-safe (buildWelcomeEmail HTML-escapea name), SMTP config leído de store_settings (smtp_host/port/secure/user/pass/from). No cambios en RBAC ni nuevos endpoints públicos.
- Cambios: identity WelcomeMailer port + SettingsWelcomeMailer; identity.routes register handler dispatch; IdentityRoutesDeps.welcomeMailer; identity/index.ts re-exporta mailers; build-app index import (R2 clean). payments.routes PaymentSucceeded → sendOrderStatusEmail({state:'PAID'}) con gate outcome.kind. orders/index.ts barrel re-exporta sendOrderStatusEmail/ORDER_STATE_LABELS. notifications: account_created en EmailTemplate union, LoggingEmailProvider SUBJECTS/BODIES y dispatchSchema enum.
- Tests: SettingsWelcomeMailer.test.ts (5) + orders-index.test.ts (1); tsc --noEmit 0 errors; prettier+eslint clean en archivos tocados; lint:boundaries sin nuevas violaciones (queda solo R1 preexistente security.routes); 197 tests pass; git diff --check clean.
- Artefactos: work/artifacts/F-152/ (architect.md, implementer.md, reviewer.json, security.json, qa.json, leader-close.json)
- Commits: feat(F-152): completed feature + chore: reset runtime after F-152 (push omitido, sin remote origin)
- Gates: reviewer APPROVED, security APPROVED, qa APPROVED, verify.sh exit 0
- Entregable: migración node-pg-migrate 048 (idempotente/reversible) añade
orders_orders.store_id(uuid NOT NULL DEFAULT default-store + FK→pos_stores(id) + idx),orders_orders.shipping_cents(integer NOT NULL DEFAULT 0),orders_items.cost_at_sale_cents(bigint nullable),orders_items.vat_rate(text nullable) — snapshots; itestreporting-snapshots.itest.ts(DB real) 3/3 - Nota: PG16 no admite
ADD CONSTRAINT IF NOT EXISTS→ FK usaDO $$guard (convención 047); el itest usaINSERT (source) VALUES ('pos')para satisfacer el CHECK de 047 - Commit:
2ea628f feat(F-144): completed feature - Artefactos:
work/artifacts/F-144/(architect.md, implementer.md, reviewer.json, security.json, qa.json, documenter.md, leader-close.json) - Siguiente: F-145 (Reporting: payment lines and POS cash-safe capture)