{
  "project": "IA × IA",
  "author": "Rodrigo Jorge",
  "lang": "en",
  "source": "https://iaxia.rodrigojorge.me/en",
  "updated": "2026-10-06",
  "families": {
    "identity-access": "Identity and access",
    "fraud-abuse": "Fraud and abuse",
    "applications-apis": "Applications and APIs",
    "endpoints": "Endpoints",
    "soc-response": "SOC and response",
    "cloud-infrastructure": "Cloud and infrastructure",
    "data-information": "Data and information",
    "brand-customers": "Brand and customers",
    "ai-agent-governance": "AI and agent governance",
    "grc-compliance": "GRC and compliance"
  },
  "cases": [
    {
      "slug": "cyberbot",
      "families": [
        "applications-apis",
        "cloud-infrastructure",
        "soc-response"
      ],
      "kind": "IN PRODUCTION",
      "number": "01",
      "updatedAt": "2026-09-14",
      "title": "Cyberbot",
      "subtitle": "From the WAF event to a block at the edge.",
      "summary": "An agent reads the traffic that got past the WAF, receives structured context, classifies the threat, and only turns a decision into an action after it clears the guardrails.",
      "metric": "< 1 min",
      "metricLabel": "from log to block",
      "tags": [
        "Availability",
        "WAF",
        "SOC",
        "Autonomy"
      ],
      "accent": "green",
      "sections": [
        {
          "title": "The problem",
          "body": [
            "Bots and automated scanners probe the infrastructure all day long. The bottleneck isn't generating more alerts. It's separating what actually deserves attention and responding while it still matters.",
            "In this real case, the LLM only looks at traffic that got past the WAF. Anything the traditional control already blocked drops out before the pipeline."
          ]
        },
        {
          "title": "The actual architecture",
          "flow": [
            [
              "WAF",
              "Every request becomes an event: IP, path, user-agent, status and action."
            ],
            [
              "Collect + filter",
              "A Worker keeps a window of events and drops what was already blocked, known assets and predictable noise."
            ],
            [
              "LLM",
              "Receives a structured summary and returns a decision as JSON."
            ],
            [
              "Guardrails",
              "Allow list, minimum confidence, exceptions, and actions enabled per category."
            ],
            [
              "Action",
              "A block with a TTL at the edge, plus an alert with evidence for review."
            ]
          ]
        },
        {
          "title": "What goes into the AI",
          "bullets": [
            "A system prompt with a blue team analyst role, the real stack, and rules for what should not be reported.",
            "Top IPs, paths and user-agents for the period, always with HTTP status and ASN.",
            "Rare paths, where directory scanners and enumeration tend to show up.",
            "Suspects pre-flagged by simple rules, such as traversal, SQLi, .env and web shells, for the AI to validate.",
            "Operational context: cloud origin, repeat offenders, and block history."
          ]
        },
        {
          "title": "What comes out of the AI",
          "body": [
            "Free text does not drive action. The output is structured so code can validate it before anything executes."
          ],
          "code": "{\n  \"clean\": false,\n  \"threats\": [{\n    \"tipo\": \"Sensitive file probing\",\n    \"categoria\": \"git_env_exposto\",\n    \"host_path\": \"api.example.com/.env\",\n    \"ip\": \"203.0.113.7\",\n    \"severidade\": \"ALTO\",\n    \"confianca\": 88,\n    \"regra_sugerida\": \"Block /.env* at the WAF\"\n  }]\n}",
          "note": "The category comes from a closed list. Severity and confidence are validated in code. If the model breaks the contract, it falls through to a fallback, never to an action."
        },
        {
          "title": "Guardrails that make autonomy possible",
          "guardrails": [
            [
              "Nothing blocks by default",
              "Automated action has to be enabled per severity and category, with a defined list and TTL."
            ],
            [
              "The allow list is absolute",
              "Customers, partners, employees and protected origins are never blocked, even on a detection."
            ],
            [
              "Minimum confidence",
              "Below the cutoff, the system alerts and leaves the decision to a person."
            ],
            [
              "Ambiguity brings in a human",
              "When the context isn't enough, automated action is not the fallback."
            ],
            [
              "Reversible action",
              "Blocks expire by TTL, and every action leaves evidence behind."
            ]
          ]
        },
        {
          "title": "Recipe for reproducing the idea",
          "columns": [
            {
              "heading": "Ingredients",
              "items": [
                "WAF/CDN logs reachable via API, Logpush, a bucket or equivalent.",
                "A scheduled job, Worker, Lambda or serverless process.",
                "An LLM that can return structured JSON.",
                "A block list the WAF consumes, with a TTL.",
                "An alert channel with a link to the evidence."
              ]
            },
            {
              "heading": "Lessons that save weeks",
              "items": [
                "Pre-filter before the LLM. Predictable noise is better handled in code.",
                "Rules for the binary calls, AI for contextual judgment.",
                "HTTP status and context change what an event means.",
                "A false positive is a bug to fix, not a reason to turn the engine off.",
                "Start in recommendation mode. Raise autonomy once you've measured confidence and error."
              ]
            }
          ]
        }
      ],
      "takeaway": "AI isn't a report generator. It acts, within limits we set.",
      "url": "https://iaxia.rodrigojorge.me/en/cases/cyberbot",
      "markdown": "https://iaxia.rodrigojorge.me/en/cases/cyberbot.md"
    },
    {
      "slug": "antifraude-contextual",
      "families": [
        "fraud-abuse",
        "identity-access"
      ],
      "kind": "IN PRODUCTION · ANONYMIZED",
      "number": "02",
      "updatedAt": "2026-09-14",
      "title": "Contextual anti-fraud",
      "subtitle": "When each signal looks normal on its own, but the combination doesn't.",
      "summary": "The engine correlates device, network, history and behavior. The gain isn't a new rule. It's finding relationships that only emerge across different sources, and repeating that investigation at scale.",
      "metric": "85–90%",
      "metricLabel": "confidence in the examples shown",
      "tags": [
        "Fraud",
        "Device",
        "Network",
        "Behavior"
      ],
      "accent": "blue",
      "sections": [
        {
          "title": "The problem",
          "body": [
            "A rule sees events. Contextual analysis tries to see the relationships between them.",
            "A human analyst can follow the reasoning once it's laid out. The challenge is doing it continuously, in seconds, for every access, across signals that live in different systems."
          ]
        },
        {
          "title": "Real example A",
          "signal": {
            "title": "Environment mismatch",
            "items": [
              [
                "Declared platform",
                "Android"
              ],
              [
                "Observed hardware",
                "Apple GPU"
              ],
              [
                "History",
                "Previous verification rejected in the back office"
              ],
              [
                "Recurrence",
                "4 accesses with the same inconsistency"
              ],
              [
                "Hypothesis",
                "Spoofing or a tampered environment"
              ],
              [
                "Confidence",
                "85%"
              ],
              [
                "Action taken",
                "Flag as fraud and block the fingerprint"
              ]
            ]
          },
          "note": "Identifiers, location, carrier, hashes and organization data have been removed."
        },
        {
          "title": "Real example B",
          "signal": {
            "title": "Network + identity + recurrence",
            "items": [
              [
                "Network",
                "Commercial VPN/proxy node"
              ],
              [
                "Correlation",
                "Multiple fingerprints aggregated"
              ],
              [
                "Infrastructure",
                "Reverse DNS and hosting reinforce the hypothesis"
              ],
              [
                "Identity",
                "More than one device tied to the same identity"
              ],
              [
                "Decision",
                "Fraud, high confidence"
              ],
              [
                "Action taken",
                "Block the exit node at the edge"
              ]
            ]
          }
        },
        {
          "title": "How the reasoning works",
          "flow": [
            [
              "Signals",
              "Device, network, approximate location, history, identity and behavior."
            ],
            [
              "Enrichment",
              "Normalizes attributes and adds technical and historical context."
            ],
            [
              "Correlation",
              "Looks for mismatches, recurrence and relationships that a single rule can't express well."
            ],
            [
              "Explainable decision",
              "Produces a hypothesis, evidence, score/confidence and a recommended action."
            ],
            [
              "Action policy",
              "Executes only pre-approved actions and records the evidence."
            ]
          ]
        },
        {
          "title": "Why not just make it another rule?",
          "body": [
            "Once we've learned that declared Android + Apple GPU + a previous rejection is suspicious, that combination can become a rule.",
            "The value of the AI is in finding the next combination: weak signals, histories and behaviors that change from case to case, while explaining why the set matters."
          ]
        },
        {
          "title": "How to reproduce it safely",
          "disclaimer": "This section is a recommended implementation pattern for anyone adapting the concept. It does not necessarily describe every control in the real system.",
          "guardrails": [
            [
              "Separate detection from action",
              "The model recommends; a policy layer decides what can be executed."
            ],
            [
              "Graduated actions",
              "Alert, challenge, throttle, block temporarily and block permanently are different levels of authority."
            ],
            [
              "Mandatory explanation",
              "A score alone isn't enough. Keep the signals that supported the hypothesis."
            ],
            [
              "Reversibility",
              "Prefer actions that can be undone quickly while you're raising autonomy."
            ],
            [
              "Operational feedback",
              "False positives and human decisions need to flow back into rules, context or the prompt."
            ]
          ]
        }
      ],
      "takeaway": "A human understands one case. The machine has to correlate thousands of them without losing context.",
      "url": "https://iaxia.rodrigojorge.me/en/cases/antifraude-contextual",
      "markdown": "https://iaxia.rodrigojorge.me/en/cases/antifraude-contextual.md"
    },
    {
      "slug": "soc-agentico",
      "families": [
        "soc-response",
        "ai-agent-governance"
      ],
      "kind": "PLAYBOOK",
      "number": "03",
      "updatedAt": "2026-09-14",
      "title": "Agentic SOC",
      "subtitle": "Triage → investigation → containment.",
      "summary": "Use agents first to cut repetitive work, then to investigate, and only then grant limited containment authority.",
      "metric": "3 levels",
      "metricLabel": "of autonomy progression",
      "tags": [
        "SOC",
        "Investigation",
        "Response"
      ],
      "accent": "purple",
      "adaptavel": true,
      "sections": [
        {
          "title": "Start with the reversible work",
          "bullets": [
            "Summarize and group duplicate alerts.",
            "Enrich IPs, users, devices and assets.",
            "Build a timeline and an initial hypothesis.",
            "Open a case with the evidence already organized."
          ]
        },
        {
          "title": "Climb one step at a time",
          "flow": [
            [
              "Triage",
              "No destructive authority."
            ],
            [
              "Investigation",
              "Queries multiple sources and tests hypotheses."
            ],
            [
              "Level 1 containment",
              "Temporary, reversible actions, always logged."
            ]
          ]
        },
        {
          "title": "The limit",
          "body": [
            "Anything destructive stays a human decision until evidence, reversibility and governance justify a different design."
          ]
        }
      ],
      "takeaway": "Autonomy isn't a switch. It's a ladder.",
      "url": "https://iaxia.rodrigojorge.me/en/cases/soc-agentico",
      "markdown": "https://iaxia.rodrigojorge.me/en/cases/soc-agentico.md"
    },
    {
      "slug": "red-team-continuo",
      "families": [
        "applications-apis",
        "cloud-infrastructure"
      ],
      "kind": "PLAYBOOK",
      "number": "04",
      "updatedAt": "2026-09-14",
      "title": "Continuous red team",
      "subtitle": "Trade the annual snapshot for a permanent test.",
      "summary": "An annual pentest goes stale on the next deploy. Agents can continuously validate the attack surface, changes and authorized attack paths.",
      "metric": "365 days",
      "metricLabel": "of continuous testing",
      "tags": [
        "Red Team",
        "Exposure",
        "Validation"
      ],
      "accent": "red",
      "adaptavel": true,
      "sections": [
        {
          "title": "The design",
          "flow": [
            [
              "Explicit scope",
              "Authorized assets and techniques."
            ],
            [
              "Agent",
              "Reconnaissance and non-destructive validation."
            ],
            [
              "Evidence",
              "Reproducible steps and impact."
            ],
            [
              "Fix queue",
              "Opens an issue/PR or routes to the owner."
            ],
            [
              "Retest",
              "Confirms the fix actually closed the path."
            ]
          ]
        },
        {
          "title": "Non-negotiable guardrails",
          "bullets": [
            "Environment and assets authorized by allow list.",
            "Rate limits and an execution window.",
            "No persistence, exfiltration or destructive techniques by default.",
            "Kill switch and a complete action trail."
          ]
        }
      ],
      "takeaway": "The goal isn't to attack more. It's to shrink the time between exposure and fix.",
      "url": "https://iaxia.rodrigojorge.me/en/cases/red-team-continuo",
      "markdown": "https://iaxia.rodrigojorge.me/en/cases/red-team-continuo.md"
    },
    {
      "slug": "appsec-pipeline",
      "families": [
        "applications-apis"
      ],
      "kind": "PLAYBOOK",
      "number": "05",
      "updatedAt": "2026-09-14",
      "title": "AppSec in the pipeline",
      "subtitle": "Found it. Fixed it. Tested it. Committed it.",
      "summary": "The agent doesn't have to stop at the finding. It can prepare the patch and the tests, leaving the review and the merge to a human.",
      "metric": "PR",
      "metricLabel": "as the unit of delivery",
      "tags": [
        "AppSec",
        "Code",
        "DevSecOps"
      ],
      "accent": "amber",
      "adaptavel": true,
      "sections": [
        {
          "title": "Recommended flow",
          "flow": [
            [
              "Finding",
              "Receives the vulnerability with repository context."
            ],
            [
              "Patch",
              "Proposes the smallest possible change."
            ],
            [
              "Test",
              "Creates or updates a test that demonstrates the fix."
            ],
            [
              "PR",
              "Opens a pull request with evidence and impact."
            ],
            [
              "Human",
              "Reviews and decides on the merge."
            ]
          ]
        },
        {
          "title": "Measure the right thing",
          "body": [
            "More findings doesn't mean more security. Measure time to fix, patch acceptance rate, regressions and recurrence."
          ]
        }
      ],
      "takeaway": "If the machine already finds everything, the advantage becomes how fast you fix it.",
      "url": "https://iaxia.rodrigojorge.me/en/cases/appsec-pipeline",
      "markdown": "https://iaxia.rodrigojorge.me/en/cases/appsec-pipeline.md"
    },
    {
      "slug": "marca-identidade",
      "families": [
        "brand-customers",
        "fraud-abuse"
      ],
      "kind": "PLAYBOOK",
      "number": "06",
      "updatedAt": "2026-09-14",
      "title": "Brand and identity",
      "subtitle": "Contextual triage at scale, with the takedown ready to go.",
      "summary": "New domains tied to campaigns and major brands show up in high volume. The challenge is separating signal from noise, prioritizing risk, and turning a confirmed detection into action.",
      "metric": "18,000",
      "metricLabel": "domains tied to Black Friday and major brands in a single month",
      "tags": [
        "Brand",
        "Fraud",
        "Takedown"
      ],
      "accent": "green",
      "adaptavel": true,
      "sections": [
        {
          "title": "Pipeline",
          "flow": [
            [
              "Discovery",
              "New domains, certificates, ads, social media accounts and pages."
            ],
            [
              "Similarity",
              "Brand, text, layout, infrastructure and behavior."
            ],
            [
              "Context",
              "Campaign, target, recurrence and relationship to legitimate assets."
            ],
            [
              "Decision",
              "Prioritizes by risk and confidence."
            ],
            [
              "Takedown",
              "Generates evidence and triggers the provider's process."
            ]
          ]
        },
        {
          "title": "Before you buy another tool",
          "body": [
            "Check whether your current providers already deliver brand protection, threat intel or abuse monitoring signals that you haven't turned on or integrated yet."
          ]
        }
      ],
      "takeaway": "Detection only creates value when it reaches an operational action.",
      "url": "https://iaxia.rodrigojorge.me/en/cases/marca-identidade",
      "markdown": "https://iaxia.rodrigojorge.me/en/cases/marca-identidade.md"
    },
    {
      "slug": "supervisor-agentes",
      "families": [
        "ai-agent-governance",
        "soc-response",
        "identity-access"
      ],
      "kind": "PLAYBOOK",
      "number": "07",
      "updatedAt": "2026-10-06",
      "title": "Agent supervisor",
      "subtitle": "More intelligence in the operator. Less power in whoever authorizes.",
      "summary": "An operator agent investigates with broad context and proposes an action. A deliberately limited supervisor evaluates the request. A Policy Engine applies the objective rules before anything executes.",
      "metric": "3 layers",
      "metricLabel": "investigate, authorize and execute",
      "tags": [
        "Agents",
        "Governance",
        "Autonomy",
        "Policy Engine"
      ],
      "accent": "blue",
      "adaptavel": true,
      "sections": [
        {
          "title": "The problem",
          "body": [
            "An autonomous agent can query SIEM, EDR, IAM, WAF and cloud, correlate signals, and arrive at a solid hypothesis. The risk shows up when the same entity that investigates also decides, on its own, how far it can act.",
            "The proposal is to separate roles and authority. The operator stays powerful for investigation. Authorization goes through a layer with a much narrower objective, less context, fewer tools and less authority."
          ]
        },
        {
          "title": "Architecture",
          "flow": [
            [
              "Operator agent",
              "The more capable model. Investigates, correlates, builds a hypothesis, gathers evidence and requests an action."
            ],
            [
              "Supervisor agent",
              "Receives only the context needed for one specific decision. Approves, denies or escalates."
            ],
            [
              "Policy Engine",
              "Applies deterministic rules: allow and deny lists, authority, asset, identity, reversibility, TTL, schema and kill switch."
            ],
            [
              "Action",
              "Executes only within the delegated authority. Outside it, a human is required."
            ]
          ],
          "note": "The supervisor doesn't need to investigate better than the operator. It needs to decide something much narrower."
        },
        {
          "title": "The contract between operator and supervisor",
          "body": [
            "The operator doesn't hand the supervisor an entire conversation. It hands over a structured request with action, target, evidence, confidence and reversibility."
          ],
          "code": "{\n  \"action\": \"revoke_session\",\n  \"target\": \"user_8271\",\n  \"evidence\": {\n    \"credential_leak\": \"confirmed\",\n    \"impossible_travel\": true,\n    \"active_sessions\": 3\n  },\n  \"operator_confidence\": 94,\n  \"reversible\": true\n}"
        },
        {
          "title": "The response is a contract too",
          "code": "{\n  \"decision\": \"APPROVE\",\n  \"policy\": \"IAM-07\",\n  \"scope\": \"user_8271\",\n  \"ttl\": \"15m\",\n  \"requires_human\": false\n}",
          "note": "Free text can explain. The authorization that moves on to the next layer has to respect a verifiable schema."
        },
        {
          "title": "Same incident. Different authority.",
          "signal": {
            "title": "Operational example",
            "items": [
              [
                "Request 1",
                "Block a malicious IP for 30 minutes"
              ],
              [
                "Supervisor",
                "APPROVE"
              ],
              [
                "Policy Engine",
                "Temporary, reversible action within the delegated authority"
              ],
              [
                "Outcome",
                "Executes automatically"
              ],
              [
                "Request 2",
                "Disable the CFO's account"
              ],
              [
                "Supervisor",
                "May consider the evidence sufficient"
              ],
              [
                "Policy Engine",
                "Privileged identity and a high-impact action"
              ],
              [
                "Outcome",
                "HUMAN APPROVAL REQUIRED"
              ]
            ]
          }
        },
        {
          "title": "The authority matrix",
          "columns": [
            {
              "heading": "Can be automated",
              "items": [
                "Enrich and correlate alerts.",
                "Build a timeline and gather evidence.",
                "Temporarily block an IP within policy.",
                "Revoke a session when identity, scope and reversibility are within the rule."
              ]
            },
            {
              "heading": "Escalates to a supervisor",
              "items": [
                "Disabling a privileged account.",
                "Changing a critical configuration.",
                "Any action with a large blast radius.",
                "Any irreversible or critical action."
              ]
            }
          ]
        },
        {
          "title": "Authority that is earned and lost",
          "body": [
            "The authority to act without approval isn't a single level for the agent, and it isn't permanent. It is granted per action class, after the agent's decisions in that class have been compared against human review on a defined sample. The agent doesn't measure its own accuracy.",
            "When verdicts start diverging from independent review beyond a threshold, the class drops back to its previous mode. The threshold, the observation window and who reviews are part of the contract, not left implicit."
          ],
          "guardrails": [
            [
              "Granted per class",
              "Enriching, blocking an IP for a limited time and revoking a session are separate classes. Each one levels up on its own, on its own evidence."
            ],
            [
              "Independent evaluation",
              "The sample of decisions is reviewed by someone who is neither the operator nor the supervisor. The agent doesn't grade its own exam."
            ],
            [
              "Demotion trigger",
              "Divergence beyond the threshold demotes the class automatically. The demotion is executed by the platform, outside the model."
            ],
            [
              "Actions in flight",
              "The contract spells out what happens to what was already executed when a class drops a level: rollback, compensation, or just a record. Expiring the authorization doesn't undo what's already done."
            ]
          ]
        },
        {
          "title": "The agent badge",
          "columns": [
            {
              "heading": "What the badge declares",
              "items": [
                "The agent's identity and its human owner.",
                "The context it can query and the access it holds.",
                "Authorized actions, per class, with each one's current level.",
                "Required supervision, required evidence, and validity with an expiration."
              ]
            },
            {
              "heading": "What stays off the badge",
              "items": [
                "The kill switch. The agent doesn't control its own shutdown.",
                "Class demotion. The platform executes it.",
                "The accuracy measurement. It comes from independent review.",
                "An agent without an identity and bounded authority is a service account with too much power."
              ]
            }
          ]
        },
        {
          "title": "What actually reduces the risk",
          "guardrails": [
            [
              "Narrow role",
              "The supervisor doesn't get an open-ended mission to investigate the whole incident. It evaluates one specific request."
            ],
            [
              "Minimal context",
              "It receives only the data needed to decide, which shrinks the surface for interpretation."
            ],
            [
              "Less authority",
              "It doesn't get free access to the environment and doesn't execute the requested action directly."
            ],
            [
              "Independence",
              "Objective, context and contract should keep it from simply replaying the operator's chain of reasoning."
            ],
            [
              "Deterministic control",
              "Objective policies stay outside the LLM whenever they can be expressed as a rule."
            ],
            [
              "Human by impact",
              "The human comes in by exception, by policy or by impact. Anything irreversible or critical requires human approval."
            ]
          ]
        },
        {
          "title": "A smaller model doesn't mean a safer model",
          "body": [
            "A smaller model can work well as a supervisor because the task is narrow, but size is no guarantee of safety. The control comes from the architecture: limited role, minimal context, strict contract, less authority, independence and deterministic validation.",
            "A second identical instance doesn't solve the problem on its own either. If the operator and the supervisor share the same assumptions, context and way of deciding, the second layer can repeat the same failure."
          ]
        },
        {
          "title": "How to implement it",
          "flow": [
            [
              "1. Catalog the actions",
              "List what your agents can request: query, block, revoke, isolate, change or delete."
            ],
            [
              "2. Classify impact",
              "Define reversibility, criticality, blast radius, and protected identities or assets."
            ],
            [
              "3. Define authority",
              "Map each action to automatic, supervisor, or human approval."
            ],
            [
              "4. Create contracts",
              "Standardize request and response with a verifiable schema and required evidence."
            ],
            [
              "5. Pull rules out of the LLM",
              "Allow list, limits, TTL, scope, privileged identities and kill switch live in code or in a policy engine."
            ],
            [
              "6. Log everything",
              "Request, evidence, decision, policy applied, execution, outcome, and any human intervention."
            ]
          ]
        }
      ],
      "takeaway": "We're not setting up one AI to trust another AI. We're separating authority.",
      "url": "https://iaxia.rodrigojorge.me/en/cases/supervisor-agentes",
      "markdown": "https://iaxia.rodrigojorge.me/en/cases/supervisor-agentes.md"
    }
  ],
  "talks": [
    {
      "slug": "ti-exames-2026",
      "title": "IA × IA",
      "event": "TI Exames",
      "date": "2026-09-21",
      "dateLabel": "Sep 21, 2026 · 7:30–9:00 PM",
      "location": "Free class with certificate",
      "version": "deck v1.1",
      "description": "Security in the age of agents. Attack and defense have changed three times while you were reading this title. Class-format version, with more time for architecture, authority and controls.",
      "pdf": "/downloads/ia-x-ia-rodrigo-jorge-ti-exames-2026.pdf"
    },
    {
      "slug": "mind-the-sec-2026",
      "title": "IA × IA",
      "event": "Mind The Sec 2026",
      "date": "2026-09-15",
      "dateLabel": "Sep 15, 2026",
      "location": "São Paulo · Kevin Mitnick Room",
      "description": "Security in the age of agents. Attack and defense have changed three times while you were reading this title.",
      "pdf": "/downloads/ia-x-ia-rodrigo-jorge-mind-the-sec-2026.pdf"
    }
  ]
}