Módulo 8: Capstone The Andes Cargo Genai Extractor

8. Proyecto final: el paquete GenAI de Andes Cargo como entregable

Descripción

Este es el proyecto de cierre de la guía completa. Reúne, en un solo repositorio verificado de punta a punta, cada pieza que los ocho módulos construyeron: bedrock.tf y modules/bedrock-guardrail/ (M3), los guardrails propios y su integración (M4), el security gate extendido con bedrock-least-privilege.rego y el .zip firmado (M5), el cost gate extendido con bedrock-budget.rego y la calculadora de costo (M2, M6), la métrica de escalamiento y el arnés de smoke test (M7), y los dos recorridos de este módulo (M8.3, M8.4). Nada de esto se construye de nuevo aquí — este proyecto lo verifica, de punta a punta, una última vez, y lo entrega como una pieza defendible de portfolio, con el ledger de honestidad de la lección 5 como su última página.

Conexión con el módulo

Como cada proyecto de cierre de esta guía, este entregable no introduce ningún concepto nuevo. Es el cierre del capstone, y de la guía completa: sesenta y cuatro lecciones, ocho módulos, un solo repositorio.


Analogía: el momento exacto de mostrar el repositorio en una entrevista

Todo el trabajo de esta guía —cada terraform plan, cada pytest, cada conftest— tuvo, desde la primera lección, un destino implícito: el momento en que alguien, en una entrevista técnica real, dice "muéstrame algo que hayas construido". Ese momento no admite un resumen en prosa de lo que hiciste — admite un repositorio que se clona, se abre, y responde a preguntas específicas con evidencia, no con promesas. Esta lección es esa preparación final: no agrega ninguna pieza nueva al repositorio, confirma que cada pieza existente responde, de verdad, a la pregunta "¿esto corre?" — y, para la única pieza que honestamente no corre en este laboratorio, tiene lista la razón exacta, sin titubear.


Paso 1 — El árbol completo del repositorio

find andes-cargo-infra/ -type f \
  -not -path "*/.terraform/*" -not -path "*/.git/*" -not -name "*.lock.hcl" \
  | sort

Qué esperar (literal — la estructura completa que los ocho módulos de esta guía dejaron, heredada de las siete guías hermanas y extendida por esta):

andes-cargo-infra/.github/workflows/ci.yml
andes-cargo-infra/ADR-001-llm-as-escalation-path.md
andes-cargo-infra/COST-PROFILE.md
andes-cargo-infra/GENAI-COST-PROFILE.md
andes-cargo-infra/RISK-MAP.md
andes-cargo-infra/THREAT-MODEL.md
andes-cargo-infra/bedrock.tf
andes-cargo-infra/cosign.key
andes-cargo-infra/cosign.pub
andes-cargo-infra/cost-policy/bedrock-budget.rego
andes-cargo-infra/cost-policy/required-cost-tags.rego
andes-cargo-infra/evals/fixtures/sample_manifests.json
andes-cargo-infra/evals/manifest_extraction_smoke_test.py
andes-cargo-infra/evals/test_manifest_extraction_smoke_test.py
andes-cargo-infra/functions/extract-shipment-manifest-fields/function.zip
andes-cargo-infra/functions/extract-shipment-manifest-fields/handler.py
andes-cargo-infra/functions/extract-shipment-manifest-fields/manifest.sig
andes-cargo-infra/functions/process-shipment-manifest/handler.py
andes-cargo-infra/functions/process-shipment-manifest/function.zip
andes-cargo-infra/functions/process-shipment-manifest/manifest.sig
andes-cargo-infra/guardrails/defense_in_depth_flow.py
andes-cargo-infra/guardrails/post_invoke_checks.py
andes-cargo-infra/guardrails/pre_invoke_checks.py
andes-cargo-infra/guardrails/test_defense_in_depth_flow.py
andes-cargo-infra/guardrails/test_post_invoke_checks.py
andes-cargo-infra/guardrails/test_pre_invoke_checks.py
andes-cargo-infra/locals.tf
andes-cargo-infra/modules/bedrock-guardrail/main.tf
andes-cargo-infra/modules/bedrock-guardrail/outputs.tf
andes-cargo-infra/modules/bedrock-guardrail/variables.tf
andes-cargo-infra/modules/iam-role/main.tf
andes-cargo-infra/modules/iam-role/outputs.tf
andes-cargo-infra/modules/iam-role/variables.tf
andes-cargo-infra/modules/s3-bucket/main.tf
andes-cargo-infra/modules/s3-bucket/outputs.tf
andes-cargo-infra/modules/s3-bucket/variables.tf
andes-cargo-infra/no-tlog-signing-config.json
andes-cargo-infra/observability/escalation_rate.py
andes-cargo-infra/observability/test_escalation_rate.py
andes-cargo-infra/policy/bedrock-least-privilege.rego
andes-cargo-infra/policy/least-privilege-iam.rego
andes-cargo-infra/policy/no-destroy-shipments.rego
andes-cargo-infra/policy/no-public-buckets.rego
andes-cargo-infra/scripts/bedrock_cost_estimate.py
andes-cargo-infra/scripts/test_bedrock_cost_estimate.py
andes-cargo-infra/variables.tf

Cuarenta y dos archivos. Ocho son genuinamente nuevos de esta guía: bedrock.tf, GENAI-COST-PROFILE.md, ADR-001-llm-as-escalation-path.md, modules/bedrock-guardrail/ (tres archivos), guardrails/ (seis archivos), functions/extract-shipment-manifest-fields/ (tres archivos), scripts/bedrock_cost_estimate.py (dos archivos), policy/bedrock-least-privilege.rego, cost-policy/bedrock-budget.rego, observability/ (dos archivos), evals/ (tres archivos). El resto —RISK-MAP.md, THREAT-MODEL.md, COST-PROFILE.md, los tres módulos de terraform-and-iac-guide, process-shipment-manifest, ci.yml, el keypair de cosign— es exactamente lo que las siete guías hermanas dejaron, sin ningún cambio de estructura.


Paso 2 — Verificación de punta a punta, cada capa

Cuatro comandos, cada uno confirmando una capa distinta del sistema, cada uno ya corrido en su propio módulo — reconfirmados aquí, juntos, una última vez:

cd andes-cargo-infra/
terraform fmt -check -recursive; echo "fmt: $?"
terraform validate
terraform plan -input=false -no-color -out=tfplan-capstone

Qué esperar (literal — Infraestructura, M3-M4):

fmt: 0
Success! The configuration is valid.
Plan: 17 to add, 0 to change, 0 to destroy.
conftest test tfplan.json -p policy/

Qué esperar (literal — Seguridad, M5):

6 tests, 6 passed, 0 warnings, 0 failures, 0 exceptions
conftest test tfplan.json -p cost-policy/

Qué esperar (literal — Costo, M2/M6):

3 tests, 3 passed, 0 warnings, 0 failures, 0 exceptions
pytest guardrails/ scripts/ observability/ evals/ -v -p no:randomly | tail -5

Qué esperar (literal — Guardrails propios + calculadora + observabilidad + evals, M2/M4/M7):

============================== 59 passed in 0.08s ===============================

Cincuenta y nueve casos: 34 de guardrails/ (M4.8), 12 de scripts/ (M2.7), 7 de observability/ (M7.4), 6 de evals/ (M7.6). Suma exacta, sin ningún caso perdido en el camino.


Paso 3 — Los dos recorridos de este módulo, sumados al total

pytest guardrails/ scripts/ observability/ evals/ \
       test_deterministic_path_walkthrough.py test_handler.py \
       -v -p no:randomly | tail -5

Qué esperar (literal — el total de toda la guía, incluidos los dos recorridos de las lecciones 3 y 4 de este módulo):

============================== 66 passed in 0.09s ===============================

Sesenta y seis casos de pytest, más nueve tests de conftest (seis de seguridad, tres de costo), más un Plan: 17 to add de Terraform, más un manifest.sig verificado con cosign — cero fallos, en toda la guía, sin ninguna excepción no declarada. Ningún número de esta lección se inventó para el cierre: cada uno es la suma exacta de lo que cada módulo anterior ya reportó por separado.


Paso 4 — El pipeline completo, heredado sin ningún carril nuevo

El M5.8 y el M6.8 ya confirmaron, cada uno por su cuenta con act pull_request real contra Docker, que los cinco jobs de ci.ymlpolicy-check, iac-scan, verify-artifact (seguridad, M5); cost-estimate, cost-tags (costo, M2/M6)— evalúan correctamente el Terraform y los artefactos de esta guía, sin necesitar ni un job nuevo ni un carril nuevo:

   CI.yml -- CINCO JOBS, DOS CARRILES, CERO JOBS NUEVOS EN TODA ESTA GUIA

   Carril de seguridad (M5)          Carril de costo (M2, M6)
        │                                    │
        ├── policy-check                     ├── cost-estimate
        │   (+ bedrock-least-privilege.rego) │   (Infracost -- auth gate,
        ├── iac-scan (Trivy)                 │    representativo, M2.5-6)
        └── verify-artifact                  └── cost-tags
            (+ manifest.sig del                  (+ bedrock-budget.rego)
             extractor, cosign)

   Sin needs: cruzado entre carriles -- ambos corren en paralelo,
   exactamente como el Modulo 1 de esta guia prometio desde el principio

Ninguna lección de esta guía, en ningún módulo, agregó un sexto job. Cada pieza nueva de Bedrock se sumó, como un step más o un archivo .rego más, a un job que ya existía — la extensión aditiva que DISENO.md prometió desde su primera línea.


Paso 5 — El ledger de honestidad, como última página

La lección 5 de este módulo ya documentó el ledger completo, con la razón técnica exacta de cada fila. Su versión condensada, para cerrar este entregable:

CapaEstado
Infraestructura (bedrock.tf, modules/bedrock-guardrail/, BedrockManifestExtractorRole)Ejecutadovalidate/plan reales, apply representativo (Ultimate-only, M3.6)
Guardrails propios (pre_invoke_checks.py, post_invoke_checks.py, defense_in_depth_flow.py)Ejecutado — 34 casos de pytest, siempre reales
Seguridad (bedrock-least-privilege.rego, firma cosign)Ejecutadoconftest/cosign reales; security gate extendido
Costo (bedrock_cost_estimate.py, bedrock-budget.rego, GENAI-COST-PROFILE.md)Ejecutado — calculadora + conftest reales; el $ de Infracost, representativo
Observabilidad (escalation_rate.py, arnés de smoke test)Ejecutado — 12,0 % y 3/5 reales; latencia/calidad, representativas
Este capstone (M8.3, M8.4)Mixto, declarado — parser y ManifestParseFailed reales; invocación a Bedrock, representativa desde el punto exacto marcado en handler.py
Cualquier invocación real a Bedrock, en toda la guíaNunca ocurrió, en ningún módulo, sin excepción

La última fila es la que sostiene a todas las demás — y es, exactamente, la que un entrevistador técnico va a preguntar primero si nota que ninguna salida de esta guía dice "tokens usados: 1.204" con un número real detrás.


Paso 6 — Cómo presentar este repositorio, frente a una pregunta difícil

Vale la pena ensayar, en voz alta, la respuesta a la pregunta más incómoda que este proyecto puede recibir: "¿corriste esto contra Bedrock de verdad?". Una respuesta defendible, con la misma disciplina de honestidad que sostuvo cada lección:

"No — y te puedo decir exactamente por qué, con evidencia. Bedrock está disponible solo en el plan Ultimate de LocalStack, de pago, así que este laboratorio corrió con LocalStack Hobby, gratuito. Lo que sí construí y verifiqué de verdad: la infraestructura completa como código, con terraform plan mostrando diecisiete recursos sin ningún error; dos guardrails propios, deterministas, con sesenta y seis casos de prueba pasando; una política de mínimo privilegio de IAM verificada con conftest contra el plan real; un artefacto firmado criptográficamente con cosign; una calculadora de costo por token con sus propios casos de prueba; y una métrica de tasa de escalamiento calculada sobre datos reales, sin necesitar ninguna invocación de modelo. Lo único que no pude ejecutar es la llamada al modelo en sí — y el código que la construiría, hasta el último parámetro, sí está ahí, listo, con la línea exacta comentada donde correría."

Esta respuesta no esconde la limitación — la nombra primero, con su razón exacta, y después demuestra la profundidad real de todo lo que sí se construyó. Es, en una sola respuesta hablada, la misma disciplina que sostuvo las sesenta y cuatro lecciones de esta guía completa.


Errores comunes

Presentar el 66 passed del Paso 3 como si incluyera alguna prueba que invoca Bedrock (de perder de vista qué prueba cada suite). Qué pasa: alguien, citando el número total, da a entender que una parte de esos 66 casos verifica una respuesta real del modelo. Cómo detectarlo: si tu descripción del Paso 3 no distingue entre "66 casos de código propio, determinista" y "cero casos que dependan de Bedrock". Cómo corregirlo: cada uno de los 66 casos —los heredados de M2/M4/M7 y los dos nuevos de este módulo— prueba código Python 100 % propio, sin ninguna dependencia de red ni de Bedrock; la fila final del ledger del Paso 5 lo confirma sin ambigüedad.

Tratar el árbol de archivos del Paso 1 como si todos los cuarenta y dos archivos fueran nuevos de esta guía (de no distinguir heredado de nuevo, el mismo error que el M3.8 ya advirtió). Qué pasa: alguien describe este proyecto como "cuarenta y dos archivos que construí". Cómo detectarlo: si tu conteo de "lo que hice en esta guía" incluye RISK-MAP.md, THREAT-MODEL.md o modules/s3-bucket/. Cómo corregirlo: el Paso 1 de esta lección ya lo distingue con precisión — ocho piezas son genuinamente nuevas de esta guía; el resto es exactamente lo que siete guías hermanas ya dejaron, heredado sin ningún cambio de estructura. Presentar el total como propio sería, exactamente, el mismo error que el M3.8 ya nombró para el conteo de 17 to add.

Ensayar la respuesta del Paso 6 memorizada palabra por palabra, sin poder sostenerla ante una pregunta de seguimiento (de memorizar en vez de entender). Qué pasa: alguien repite la cita del Paso 6 de memoria, pero no puede contestar una pregunta de seguimiento como "¿y qué es exactamente el plan Ultimate?" o "¿cuántos casos de prueba tiene el validador de esquema, específicamente?". Cómo detectarlo: si tu única fuente para defender este proyecto es la cita textual de esta lección, sin haber corrido tú mismo ninguno de los comandos de los Pasos 2 y 3. Cómo corregirlo: la cita del Paso 6 es un punto de partida, no un guion completo — la defensa real de este proyecto viene de haber corrido, tú mismo, terraform plan, pytest, conftest y cosign verify-blob, en tu propia máquina, con tus propios ojos viendo la salida — exactamente lo que cada lección de esta guía, desde el M1.7, te pidió hacer, no solo leer.


Ejercicios

Ejercicio 1 — Sin mirar el Paso 1, lista de memoria las ocho piezas genuinamente nuevas de esta guía (no heredadas de una guía hermana). Verifica tu lista contra el Paso 1 de esta lección.

Ver solución

bedrock.tf, GENAI-COST-PROFILE.md, ADR-001-llm-as-escalation-path.md, modules/bedrock-guardrail/, guardrails/ (los tres scripts propios más sus pruebas), functions/extract-shipment-manifest-fields/, scripts/bedrock_cost_estimate.py, policy/bedrock-least-privilege.rego, cost-policy/bedrock-budget.rego, observability/, evals/. Si nombraste la mayoría sin ayuda, tienes clara la frontera exacta entre lo que esta guía construyó y lo que heredó.

Ejercicio 2 — Un entrevistador pregunta: "¿por qué solo 66 casos de prueba, y no más, para un sistema con tanta superficie?" Responde con precisión, sin exagerar ni minimizar.

Ver solución

Una respuesta completa suena, más o menos, así: "66 es el número exacto de casos que el código propio de esta guía necesita para estar bien probado, no un número elegido de antemano — cada suite creció orgánicamente con cada pieza nueva: 11 para el scrubber de PII, 16 para el validador de esquema, 7 para su integración, 12 para la calculadora de costo, 7 para la tasa de escalamiento, 6 para el arnés de smoke test, y 7 más de este módulo de cierre. Ninguna parte de la superficie del sistema que SÍ es código propio y determinista quedó sin su propio caso de prueba. Lo que este número no cubre —y no podría cubrir sin invocar Bedrock de verdad— es la calidad de una extracción real, que es, honestamente, territorio de AI Engineering, no de esta guía."

Ejercicio 3 — Predice qué le pasaría al número Plan: 17 to add del Paso 2 si, en una entrevista, mostraras este repositorio contra una cuenta AWS real por primera vez. ¿Cambiaría el número, o solo el resultado de apply?

Ver solución

El número 17 to add no cambiaría — es el resultado de terraform plan, que depende únicamente del HCL declarado y de que el state esté vacío (ningún recurso creado todavía), no de si la cuenta detrás es LocalStack o AWS real. Lo que sí cambiaría es que, por primera vez, terraform apply podría ejecutarse de verdad contra los diecisiete recursos —incluido el guardrail de Bedrock, que en este laboratorio nunca pasó de plan—, y a partir de ahí, invocaciones reales a bedrock:InvokeModel se volverían posibles. El código de este repositorio, en ese momento, no necesitaría ningún cambio — la misma relación exacta que el M3.6 y el M8.5 de esta guía ya establecieron: el código es el mismo, cambia si el servicio detrás existe.


Resumen y siguiente paso

Este proyecto final reunió los cuarenta y dos archivos del repositorio de Andes Cargo —ocho genuinamente nuevos de esta guía, el resto heredado sin cambios de siete guías hermanas—, y los verificó de punta a punta, una última vez: terraform plan con diecisiete recursos, sin cambios; seis tests de seguridad y tres de costo, todos limpios con conftest; sesenta y seis casos de pytest, incluidos los dos recorridos de este módulo, sin ningún fallo; y el pipeline completo de dos carriles, cinco jobs, cero jobs nuevos en toda la guía. Cerraste con el ledger de honestidad de la lección 5 como última página, y ensayaste la respuesta exacta a la pregunta más difícil que este proyecto puede recibir.

Con este entregable, genai-on-aws-production-guide completa — ocho módulos, sesenta y cuatro lecciones, desde el problema de por qué un modelo que responde bien en un playground no dice nada sobre producción, hasta este repositorio verificado, defendible, honesto en cada línea sobre qué corrió de verdad y qué no. Andes Cargo tiene su primera carga de trabajo de IA generativa: desplegada como código, asegurada con dos capas de defensa, costeada antes de gastar un dólar, y observada con el primer SLI de IA de todo su sistema — construida, exactamente, hasta donde este laboratorio $0 permite llegar, sin fingir ni un paso más allá.

Recursos

  1. Este mismo curso, Módulo 8, lección 5 (05-what-this-guide-left-representative.md) — el ledger de honestidad completo, con la razón técnica y la fuente exacta de cada fila condensada en el Paso 5 de esta lección.
  2. Este mismo curso, Módulo 5, lección 8 y Módulo 6, lección 8 — las dos corridas reales de act pull_request que confirman los cinco jobs de ci.yml, reconfirmadas sin repetición en el Paso 4 de esta lección.
  3. genai-on-aws-production-guide/DISENO.md — la fuente completa del diseño de esta guía, el documento que esta guía entera cumplió, módulo por módulo.
  4. AWS — Amazon Bedrock · AWS — Bedrock Guardrails · AWS — Bedrock Pricing — el panorama oficial completo del servicio que esta guía entera operó alrededor, sin invocarlo nunca.