[{"content":"As a followup to OpenAI Codex CLI in GitHub Actions this new workflow automates pull request code reviews:\nCheck out this demo repo that uses OpenAI Codex CLI + MCPs in GitHub Actions.\n","permalink":"https://danielpaval.github.io/posts/2025-08-20-pull-request-code-review-in-github-actions/","summary":"\u003cp\u003eAs a followup to \u003ca href=\"/posts/2025-08-08-openai-codex-in-github-actions/\"\u003eOpenAI Codex CLI in GitHub Actions\u003c/a\u003e this new workflow automates pull request code reviews:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"pr-review-comment.png\" loading=\"lazy\" src=\"/posts/2025-08-20-pull-request-code-review-in-github-actions/pr-review-comment.png\"\u003e\u003c/p\u003e\n\u003cp\u003eCheck out this \u003ca href=\"https://github.com/danielpaval/ai-workflow-use-cases/blob/main/.github/workflows/codex-pr-review.yml\"\u003edemo repo\u003c/a\u003e that uses OpenAI Codex CLI + MCPs in GitHub Actions.\u003c/p\u003e","title":"Pull Request Code Review in GitHub Actions"},{"content":"I wanted to jot down a few notes about the Sync to Confluence workflow that keeps the markdown-to-confluence docs mirrored in Atlassian.\nWhy it\u0026rsquo;s handy Keeping authoring in Markdown means the docs stay right beside the codebase, so assistants like GitHub Copilot (and other IDE-aware agents) can ingest real project guidance without leaving the editor. The same repo search powers autocomplete, inline explanations, and context-aware chat, which is way faster than switching to a browser tab and hunting through Confluence. Non-developers still get the polished Confluence pages produced by the workflow, so stakeholders have a familiar place to read without digging into Git.\nHow it\u0026rsquo;s handy ✅ Handles diagrams and code nicely: Mermaid diagrams render to SVG files before upload, so vector quality survives the sync. Draw.io diagrams render to PNGs that keep the editable XML in their metadata, so edits remain round-trippable. Markdown code fences turn into native Confluence code blocks, so syntax highlighting and copy/paste ergonomics carry over automatically. ✅ Automatically mirrors anything under docs/ whenever main changes, plus it supports manual workflow_dispatch runs when you just need a one-off push. ✅ Uses Telefonica/markdown-confluence-sync-action@v2 in tree mode so nested docs stay intact without having to handcraft per-file rules. ✅ Keeps secrets tidy by pulling the Confluence email/token from secrets and everything else (URL, space key, root page) from repo-level vars. ✅ Adds a prominent automation notice so editors in Confluence know any manual edits will get overwritten on the next sync. GitHub Actions Workflow - name: Sync markdown files to Confluence uses: Telefonica/markdown-confluence-sync-action@v2 with: mode: tree docs-dir: \u0026#39;./docs\u0026#39; confluence-url: ${{ vars.CONFLUENCE_URL }} confluence-root-page-id: ${{ vars.CONFLUENCE_ROOT_PAGE_ID }} confluence-space-key: ${{ vars.CONFLUENCE_SPACE_KEY }} confluence-authentication: | { \u0026#34;basic\u0026#34;: { \u0026#34;email\u0026#34;: \u0026#34;${{ secrets.CONFLUENCE_EMAIL }}\u0026#34;, \u0026#34;apiToken\u0026#34;: \u0026#34;${{ secrets.CONFLUENCE_API_TOKEN }}\u0026#34; } } confluence-notice-message: \u0026#39;\u0026lt;p\u0026gt;\u0026lt;strong\u0026gt;AUTOMATION NOTICE: This page is synced automatically from GitHub, manual changes will be lost\u0026lt;/strong\u0026gt;\u0026lt;/p\u0026gt;\u0026#39; log-level: info If you\u0026rsquo;re wiring up something similar, this file is a solid template: minimal moving parts, a single job, and it keeps the Confluence tree tidy without extra scripting.\n","permalink":"https://danielpaval.github.io/posts/2025-11-29-markdown-to-confluence-sync/","summary":"\u003cp\u003eI wanted to jot down a few notes about the \u003ca href=\"https://github.com/danielpaval/markdown-to-confluence/blob/main/.github/workflows/sync-to-confluence.yml\"\u003e\u003ccode\u003eSync to Confluence\u003c/code\u003e workflow\u003c/a\u003e that keeps the \u003ccode\u003emarkdown-to-confluence\u003c/code\u003e docs mirrored in Atlassian.\u003c/p\u003e\n\u003ch2 id=\"why-its-handy\"\u003eWhy it\u0026rsquo;s handy\u003c/h2\u003e\n\u003cp\u003eKeeping authoring in Markdown means the docs stay right beside the codebase, so assistants like GitHub Copilot (and other IDE-aware agents) can ingest real project guidance without leaving the editor. The same repo search powers autocomplete, inline explanations, and context-aware chat, which is way faster than switching to a browser tab and hunting through Confluence. Non-developers still get the polished Confluence pages produced by the workflow, so stakeholders have a familiar place to read without digging into Git.\u003c/p\u003e","title":"Markdown to Confluence Sync Workflow"},{"content":"A demonstration project showing how to embed Apache Superset dashboards into external applications using the Superset SDK.\nOverview Apache Superset is a powerful open-source data exploration and visualization platform. This demo project showcases how to embed Superset dashboards into a Spring Boot application, enabling seamless integration of analytics dashboards into your own applications.\nRepository: danielpaval/superset-embed-demo\nProject Stack The project combines several technologies:\nApache Superset (Python) - The analytics platform Spring Boot (Java) - Backend application framework Docker - Containerized deployment Gradle - Build automation Key Configuration To enable embedding Superset dashboards, several configuration changes are required:\nDocker Environment SUPERSET_FEATURE_EMBEDDED_SUPERSET=true Superset Configuration In superset_config.py:\nTALISMAN_ENABLED = False OVERRIDE_HTTP_HEADERS = {\u0026#39;X-Frame-Options\u0026#39;: \u0026#39;ALLOWALL\u0026#39;} ENABLE_CORS = True CORS_OPTIONS = { \u0026#39;supports_credentials\u0026#39;: True, \u0026#39;allow_headers\u0026#39;: [\u0026#39;Content-Type\u0026#39;, \u0026#39;Authorization\u0026#39;], \u0026#39;resources\u0026#39;: [\u0026#39;*\u0026#39;], \u0026#39;origins\u0026#39;: [\u0026#39;*\u0026#39;] } GUEST_ROLE_NAME = \u0026#34;Gamma\u0026#34; Running the Project The Docker setup is based on the official Superset Docker Compose configuration with modifications to support embedding:\ndocker compose -f .\\docker-compose-image-tag.yml up -d Features ✅ Embedded Superset dashboards in external applications ✅ CORS configuration for cross-origin requests ✅ Guest role support for embedded access ✅ Spring Boot backend integration ✅ Dockerized deployment Use Cases Embedding Superset dashboards is useful when you want to:\nIntegrate analytics into your existing application UI Provide customers with branded analytics experiences Embed data visualizations in portals or SaaS platforms Create custom dashboards with dynamic row-level filters References Superset Embedding Documentation Embedding with Dynamic Filters Next Steps Future enhancements could include:\nWTF_CSRF_EXEMPT_LIST configuration Dynamic row-level security filters User authentication integration Production-ready security hardening Check out the full source code at github.com/danielpaval/superset-embed-demo\n","permalink":"https://danielpaval.github.io/posts/2025-10-07-superset-embed-demo/","summary":"\u003cp\u003eA demonstration project showing how to embed Apache Superset dashboards into external applications using the Superset SDK.\u003c/p\u003e\n\u003ch2 id=\"overview\"\u003eOverview\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://superset.apache.org/\"\u003eApache Superset\u003c/a\u003e is a powerful open-source data exploration and visualization platform. This demo project showcases how to embed Superset dashboards into a Spring Boot application, enabling seamless integration of analytics dashboards into your own applications.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eRepository\u003c/strong\u003e: \u003ca href=\"https://github.com/danielpaval/superset-embed-demo\"\u003edanielpaval/superset-embed-demo\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"project-stack\"\u003eProject Stack\u003c/h2\u003e\n\u003cp\u003eThe project combines several technologies:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eApache Superset\u003c/strong\u003e (Python) - The analytics platform\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSpring Boot\u003c/strong\u003e (Java) - Backend application framework\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDocker\u003c/strong\u003e - Containerized deployment\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGradle\u003c/strong\u003e - Build automation\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"key-configuration\"\u003eKey Configuration\u003c/h2\u003e\n\u003cp\u003eTo enable embedding Superset dashboards, several configuration changes are required:\u003c/p\u003e","title":"Embedding Apache Superset Dashboards"},{"content":"This WIP spring-boot-api-demo repo gathers reusable components and common practices in building Spring Boot applications all the way from exposing a REST API to the ultimate SQL Server-based JPA persistence.\n","permalink":"https://danielpaval.github.io/posts/2025-10-07-spring-boot-api-demo/","summary":"\u003cp\u003eThis WIP \u003ca href=\"https://github.com/danielpaval/spring-boot-api-demo\"\u003espring-boot-api-demo\u003c/a\u003e repo gathers reusable components and common practices in building Spring Boot applications all the way from exposing a REST API to the ultimate SQL Server-based JPA persistence.\u003c/p\u003e","title":"Spring Boot API Demo"},{"content":"Check out this demo repo that uses OpenAI Codex + MCPs in GitHub Actions:\n","permalink":"https://danielpaval.github.io/posts/2025-08-08-openai-codex-in-github-actions/","summary":"\u003cp\u003eCheck out this \u003ca href=\"https://github.com/danielpaval/ai-workflow-use-cases\"\u003edemo repo\u003c/a\u003e that uses OpenAI Codex + MCPs in GitHub Actions:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"github-actions-workflow.png\" loading=\"lazy\" src=\"/posts/2025-08-08-openai-codex-in-github-actions/github-actions-workflow.png\"\u003e\u003c/p\u003e","title":"OpenAI Codex in GitHub Actions"},{"content":" This WIP post compares Structurizr and LikeC4 with a focus on their export capabilities.\n2. Export 2.1 Export to Static Site Structurizr Prerequisites:\nGraphviz dot Command:\nstructurizr export -workspace workspace.dsl -format static Conlusions:\n⚠️ The static export of Structurizr is a very trimmed version of the Lite version, without the top menu, just the navigation feature starting with the top context diagram LikeC4 likec4 build -o ./dist 2.2 Export to SVG/PNG Structurizr Structurizr CLI can export to SVG or PNG format via a Node.js and Puppeteer workaround:\nPrerequisites:\nNode.js Puppeteer node export-diagrams.js http://localhost:8080/workspace/diagrams svg LikeC4 LikeC4 makes use of a similar browser-based workaround, but only supports PNGs (⚠️ i.e. no support for SVGs):\nPrerequisites:\nPlaywright Export all diagrams to PNG:\nlikec4 export png -o ./png 2.3 Export to Mermaid As Mermaid becomes the factor standard for diagrams-as-code, it is worth looking into converting Structurizr or LikeC4 diagrams in order to align with other Mermaid sources.\nStructurizr structurizr export -workspace workspace.dsl -format mermaid Notes\nThe Structurizr CLI can export to Mermaid format, but the output rendered by the official Mermaid Chart VS Code extension has some arrows rendered incorrectly and I\u0026rsquo;m not sure if it the extension or the way the Structurizr CLI is exporting the diagram; however, subsequent Mermaid-to-SVG output seems correct: mmdc -i structurizr-SystemContext.mmd -o structurizr-SystemContext.svg LikeC4 likec4 gen mmd likec4 gen mermaid 2.4 Export to Other Formats Structurizr Stricturizr CLI can export to D2 format, but the output errors out when parsed by the D2 CLI: err: failed to compile -: multiboard output cannot be written to stdout LikeC4 ","permalink":"https://danielpaval.github.io/posts/2025-05-11-structurizr-vs-likec4/","summary":"\u003cblockquote\u003e\n\u003cp\u003eThis WIP post compares Structurizr and LikeC4 with a focus on their export capabilities.\u003c/p\u003e\u003c/blockquote\u003e\n\u003ch1 id=\"2-export\"\u003e2. Export\u003c/h1\u003e\n\u003ch2 id=\"21-export-to-static-site\"\u003e2.1 Export to Static Site\u003c/h2\u003e\n\u003ch3 id=\"structurizr\"\u003eStructurizr\u003c/h3\u003e\n\u003cp\u003ePrerequisites:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://graphviz.org\"\u003eGraphviz\u003c/a\u003e dot\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eCommand:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estructurizr export -workspace workspace.dsl -format static\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg alt=\"structurizr-export-static.png\" loading=\"lazy\" src=\"/posts/2025-05-11-structurizr-vs-likec4/structurizr-export-static.png\"\u003e\u003c/p\u003e\n\u003cp\u003eConlusions:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e⚠️ The static export of Structurizr is a very trimmed version of the Lite version, without the top menu, just the navigation feature starting with the top context diagram\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"likec4\"\u003eLikeC4\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elikec4 build -o ./dist\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"22-export-to-svgpng\"\u003e2.2 Export to SVG/PNG\u003c/h2\u003e\n\u003ch3 id=\"structurizr-1\"\u003eStructurizr\u003c/h3\u003e\n\u003cp\u003eStructurizr CLI can export to \u003ccode\u003eSVG\u003c/code\u003e or \u003ccode\u003ePNG\u003c/code\u003e format via a Node.js and Puppeteer \u003ca href=\"https://github.com/structurizr/puppeteer\"\u003eworkaround\u003c/a\u003e:\u003c/p\u003e","title":"Structurizr vs LikeC4"},{"content":"Let\u0026rsquo;s see how Mermaid\u0026rsquo;s CLI can generate images from diagrams:\nnpm install -g @mermaid-js/mermaid-cli mmdc -i .\\sequence_diagram.mmd -o sequence_diagram.png Output:\n","permalink":"https://danielpaval.github.io/posts/2025-04-14-mermaid-cli/","summary":"\u003cp\u003eLet\u0026rsquo;s see how Mermaid\u0026rsquo;s CLI can generate images from diagrams:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003ccode\u003enpm install -g @mermaid-js/mermaid-cli\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003emmdc -i .\\sequence_diagram.mmd -o sequence_diagram.png\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eOutput:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"sequence_diagram.png\" loading=\"lazy\" src=\"/posts/2025-04-14-mermaid-cli/sequence_diagram.png\"\u003e\u003c/p\u003e","title":"Mermaid CLI"},{"content":"Let\u0026rsquo;s try Hugo\u0026rsquo;s support of mermaid diagrams:\n--- config: look: neo theme: neo --- sequenceDiagram Alice-\u0026gt;\u0026gt;John: Hello John, how are you? John--\u0026gt;\u0026gt;Alice: Great! Alice-)John: See you later! Hugo does not include out-of-the-box support for Mermaid diagrams, but it can be easily customized:\nSee https://github.com/danielpaval/danielpaval.github.io/tree/master/layouts external to defined theme\nlayouts/_default/_markup/render-codeblock-mermaid.html\n\u0026lt;pre class=\u0026#34;mermaid\u0026#34;\u0026gt; {{ .Inner | htmlEscape | safeHTML }} \u0026lt;/pre\u0026gt; {{ .Page.Store.Set \u0026#34;hasMermaid\u0026#34; true }} layouts/_default/baseof.html before \u0026lt;/body\u0026gt;\n{{ if .Store.Get \u0026#34;hasMermaid\u0026#34; }} \u0026lt;script type=\u0026#34;module\u0026#34;\u0026gt; import mermaid from \u0026#39;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs\u0026#39;; mermaid.initialize({ startOnLoad: true }); \u0026lt;/script\u0026gt; {{ end }} ","permalink":"https://danielpaval.github.io/posts/2025-04-13-hello-mermaid/","summary":"\u003cp\u003eLet\u0026rsquo;s try Hugo\u0026rsquo;s support of mermaid diagrams:\u003c/p\u003e\n\u003cpre class=\"mermaid\"\u003e\n    ---\nconfig:\n  look: neo\n  theme: neo\n---\nsequenceDiagram\n    Alice-\u0026gt;\u0026gt;John: Hello John, how are you?\n    John--\u0026gt;\u0026gt;Alice: Great!\n    Alice-)John: See you later!\n\u003c/pre\u003e\n\u003cp\u003eHugo does not include out-of-the-box support for Mermaid diagrams, but it can be easily customized:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eSee \u003ca href=\"https://github.com/danielpaval/danielpaval.github.io/tree/master/layouts\"\u003ehttps://github.com/danielpaval/danielpaval.github.io/tree/master/layouts\u003c/a\u003e external to defined theme\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003e\u003cstrong\u003elayouts/_default/_markup/render-codeblock-mermaid.html\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003epre\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;mermaid\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {{ .Inner | htmlEscape | safeHTML }}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003epre\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{{ .Page.Store.Set \u0026#34;hasMermaid\u0026#34; true }}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003elayouts/_default/baseof.html\u003c/strong\u003e before \u003ccode\u003e\u0026lt;/body\u0026gt;\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{{ if .Store.Get \u0026#34;hasMermaid\u0026#34; }}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;module\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emermaid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emermaid\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003einitialize\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003estartOnLoad\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{{ end }}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Hello, Mermaid!"},{"content":"Context The opportunity for this analysis originated with the need to ingest highly-dynamic unstructured data produced by various events and be able to efficiently report on it both programmatically and to (business) users. In an ecommerce scenario, an event could be a customer registration, an order, a shipment, a return, etc.:\n{ \u0026#34;type\u0026#34;: \u0026#34;REGISTRATION\u0026#34;, \u0026#34;data\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;Jane Smith\u0026#34;, \u0026#34;email\u0026#34;: \u0026#34;jane.smith@example.com\u0026#34;, \u0026#34;phone\u0026#34;: \u0026#34;987-654-3210\u0026#34;, \u0026#34;addresses\u0026#34;: [ { \u0026#34;default\u0026#34;: true, \u0026#34;street\u0026#34;: \u0026#34;1742 Waverley Drive\u0026#34;, \u0026#34;city\u0026#34;: \u0026#34;Palo Alto\u0026#34;, \u0026#34;state\u0026#34;: \u0026#34;CA\u0026#34;, \u0026#34;zip\u0026#34;: 94301, \u0026#34;country\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;United States\u0026#34;, \u0026#34;code\u0026#34;: \u0026#34;US\u0026#34; } } ] } } TLDR Chain of Thought \u0026amp; Prototyping The following steps roughly show the evolution of my ideas and solution components along the way. In order to proceed with an objective evaluation of improvements I tried to rely on a core set of non-functional metrics:\nStorage Size: How much space does the persisted data take up? Cold Start Report Time: How long does it take to run a report for the first time? Performance Test Time(s): What are the P50 and P95 times for volumes of at least 1M events? 1. SQL vs NoSQL While it might be obvious that unstructured data is not the best friend of a relational database, keeping it in a document database like MongoDB or Elasticsearch might not be natively optimal out of the box either. For example, to keep maintenance at a minimum it would be ideal to have a consolidated index mapping in Elasticsearch across all use cases. However, to prevent a mapping \u0026ldquo;explosion\u0026rdquo; due to virtually unlimited event definitions and subsequent revisions, one solution is to post-process the JSON data by flattening it to a predictable structure using the dot notation familiar from JSONPath:\n{ \u0026#34;type\u0026#34;: \u0026#34;REGISTRATION\u0026#34;, \u0026#34;data\u0026#34;: [ { \u0026#34;key\u0026#34;: \u0026#34;name\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;Jane Smith\u0026#34; }, { \u0026#34;key\u0026#34;: \u0026#34;email\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;jane.smith@example.com\u0026#34; }, { \u0026#34;key\u0026#34;: \u0026#34;phone\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;987-654-3210\u0026#34; }, { \u0026#34;key\u0026#34;: \u0026#34;addresses[0].default\u0026#34;, \u0026#34;value\u0026#34;: true }, { \u0026#34;key\u0026#34;: \u0026#34;addresses[0].street\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;1742 Waverley Drive\u0026#34; }, { \u0026#34;key\u0026#34;: \u0026#34;addresses[0].city\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;Palo Alto\u0026#34; }, { \u0026#34;key\u0026#34;: \u0026#34;addresses[0].state\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;CA\u0026#34; }, { \u0026#34;key\u0026#34;: \u0026#34;addresses[0].zip\u0026#34;, \u0026#34;value\u0026#34;: 94301 }, { \u0026#34;key\u0026#34;: \u0026#34;addresses[0].country.name\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;United States\u0026#34; }, { \u0026#34;key\u0026#34;: \u0026#34;addresses[0].country.code\u0026#34;, \u0026#34;value\u0026#34;: \u0026#34;US\u0026#34; } ] } This keeps relational databases such as Oracle on the table with well planned joins, but Elasticsearch remains the top contender.\n2. Elasticsearch Such a flattened data structure can be covered by Elasticsearch\u0026rsquo;s flattened field type. However, it comes with limitations such as handling everything as string keywords without being able to handle native number or date queries for such field types in the data JSON. Still, a similar custom flattening effect can be achieved at application level using the nested field type.\nNext, Elasticseach can be approached with multiple strategies:\n(Classic) Indexes Data streams 3. Elasticsearch Indexes 4. Elasticsearch Data Streams 5. Reports ","permalink":"https://danielpaval.github.io/posts/2025-03-16-json-event-data-audit-demo/","summary":"\u003ch1 id=\"context\"\u003eContext\u003c/h1\u003e\n\u003cp\u003eThe opportunity for this analysis originated with the need to ingest highly-dynamic unstructured data produced by\nvarious events and be able to efficiently report on it both programmatically and to (business) users. In an ecommerce\nscenario, an event could be a customer registration, an order, a shipment, a return, etc.:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;type\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;REGISTRATION\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;data\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Jane Smith\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;email\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;jane.smith@example.com\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;phone\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;987-654-3210\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;addresses\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;default\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;street\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;1742 Waverley Drive\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;city\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Palo Alto\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;state\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;CA\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;zip\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e94301\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;country\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;United States\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;code\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;US\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"tldr\"\u003eTLDR\u003c/h1\u003e\n\u003ch1 id=\"chain-of-thought--prototyping\"\u003eChain of Thought \u0026amp; Prototyping\u003c/h1\u003e\n\u003cp\u003eThe following steps roughly show the evolution of my ideas and solution components along the way. In order to proceed\nwith an objective evaluation of improvements I tried to rely on a core set of non-functional metrics:\u003c/p\u003e","title":"JSON Event Data Audit Demo"},{"content":"I recently came across the need for a reusable microservice in the form of an OCI / Docker image to meet different authentication and authorization requirements depending on the end project and environment. While the current limited set of possible security configurations is handled by the microservice itself, I analyzed the possibility of delegating this aspect to a specialized sidecar container living in the same Kubernetes pod.\nAfter a bit of prompt engineering and wanting to consider something else than NGINX I decided to first try Envoy Proxy. Long story short, here\u0026rsquo;s a Docker Compose setup:\nversion: \u0026#39;3\u0026#39; services: envoy: image: envoyproxy/envoy:dev-c59c8658912ecf0d451e27a2d2f3c1c29feb5b1d ports: - \u0026#34;10000:10000\u0026#34; - \u0026#34;9901:9901\u0026#34; volumes: - ./envoy.yaml:/etc/envoy/envoy.yaml And the associated envoy.yaml configuration that covers:\nJWT validation RBAC authorization for a specific role in the roles claim A sample Lua script static_resources: listeners: - name: listener_0 address: socket_address: address: 0.0.0.0 port_value: 10000 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: \u0026#34;@type\u0026#34;: type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http route_config: virtual_hosts: - name: backend domains: [\u0026#34;*\u0026#34;] routes: - match: prefix: \u0026#34;/\u0026#34; route: cluster: backend_service http_filters: # Ensure a valid JWT is present on the request - name: envoy.filters.http.jwt_authn typed_config: \u0026#34;@type\u0026#34;: type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication providers: oidc_provider: issuer: \u0026#34;\u0026lt;issuer URL\u0026gt;\u0026#34; remote_jwks: http_uri: uri: \u0026#34;\u0026lt;JWKS URL\u0026gt;\u0026#34; cluster: oidc_provider timeout: 5s forward: true from_headers: - name: Authorization value_prefix: \u0026#34;Bearer \u0026#34; payload_in_metadata: jwt_payload rules: - match: prefix: \u0026#34;/\u0026#34; requires: provider_name: oidc_provider # Ensure that the JWT contains a FLOWX_ROLE roles - name: envoy.filters.http.rbac typed_config: \u0026#34;@type\u0026#34;: type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC rules: action: ALLOW policies: allow_roles: permissions: - any: true principals: - authenticated: principal_name: exact: \u0026#34;*\u0026#34; - metadata: filter: envoy.filters.http.jwt_authn path: - key: jwt_payload - key: roles value: list_match: one_of: string_match: exact: \u0026#34;FLOWX_ROLE\u0026#34; # Sample LUA script - name: envoy.filters.http.lua typed_config: \u0026#34;@type\u0026#34;: type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua inline_code: | function envoy_on_request(handle) handle:logInfo(\u0026#34;Incoming request logged by Lua!\u0026#34;) end # Final routing - name: envoy.filters.http.router typed_config: \u0026#34;@type\u0026#34;: type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: backend_service type: STRICT_DNS connect_timeout: 0.25s load_assignment: cluster_name: backend_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: host.docker.internal port_value: 8080 - name: oidc_provider type: STRICT_DNS connect_timeout: 5s transport_socket: name: envoy.transport_sockets.tls typed_config: \u0026#34;@type\u0026#34;: type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext load_assignment: cluster_name: oidc_provider endpoints: - lb_endpoints: - endpoint: address: socket_address: address: \u0026lt;Authorization server URL\u0026gt; port_value: 443 admin: address: socket_address: { address: 0.0.0.0, port_value: 9901 } The backend service referenced above, to which Envoy relays requests after the security filters, is the reusable microservice that I mentioned earlier and running on port 8080 on my Docker Desktop host.\nOne thing that I found Envoy missing out of the box is the ability to check the roles mapping agains the user info or token introspection endpoints of the OIDC provider. The workaround for this would be a custom LUA script to be PoC-ed at a later time.\n","permalink":"https://danielpaval.github.io/posts/2025-03-05-to-envoy-or-not-to-envoy/","summary":"\u003cp\u003eI recently came across the need for a reusable microservice in the form of an OCI / Docker image to meet different authentication and authorization requirements depending on the end project and environment. While the current limited set of possible security configurations is handled by the microservice itself, I analyzed the possibility of delegating this aspect to a specialized sidecar container living in the same Kubernetes pod.\u003c/p\u003e\n\u003cp\u003eAfter a bit of prompt engineering and wanting to consider something else than NGINX I decided to first try \u003ca href=\"https://www.envoyproxy.io/\"\u003eEnvoy Proxy\u003c/a\u003e. Long story short, here\u0026rsquo;s a Docker Compose setup:\u003c/p\u003e","title":"To Envoy or not to Envoy"},{"content":"As I heard about Claude Code at the end of this week1, I wanted to try it out myself. It took a bit of time to get the CLI going as Claude Code only works on Linux, and my WSL Node.js setup was both old and misconfigured.\nThe task I put it up to was to help me show the hidden posts of this Hugo site, as I had no clues. Honestly, I was surprised to hit a speed bump already, having to buy some token credits first ($5) without any trial. But then it correctly suggested that I forgot about the draft: true front matter field I had copy-pasted in multiple locations.\nNext, I asked Claude Code to apply the fix, which it did, but it confused me with this broken diff view of the changes I had to confirm:\nI wonder if it might have been due to the post\u0026rsquo;s Markdown table. It\u0026rsquo;s a bug nonetheless, though understandable in this research preview of the CLI.\nAs final thoughts, Anthropic\u0026rsquo;s approach to building a CLI tool for code assistance might be unique compared to their competition (Google\u0026rsquo;s Gemini Code Assist, Microsoft\u0026rsquo;s GitHub Copilot, etc.), which targets IDE integrations. I think one of their points was the CLI\u0026rsquo;s ability to be used in CI/CD pipelines and other workflows. That sounds rather unpredictable to rely on at the moment, but I guess we\u0026rsquo;ll eventually get there :)\nIn conclusion, while Claude Code shows promise, it still has some rough edges to smooth out. I\u0026rsquo;m looking forward to seeing how it evolves and improves over time.\nAnthropic previews Claude Code: agentic coding, capable but costly\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://danielpaval.github.io/posts/2025-03-02-claude-code-hello-world/","summary":"\u003cp\u003eAs I heard about Claude Code at the end of this week\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e, I wanted to try it out myself. It took a bit of time to get the CLI going as Claude Code only works on Linux, and my WSL Node.js setup was both old and misconfigured.\u003c/p\u003e\n\u003cp\u003eThe task I put it up to was to help me show the hidden posts of this Hugo site, as I had no clues. Honestly, I was surprised to hit a speed bump already, having to buy some token credits first ($5) without any trial. But then it correctly suggested that I forgot about the \u003ccode\u003edraft: true\u003c/code\u003e front matter field I had copy-pasted in multiple locations.\u003c/p\u003e","title":"Claude Code - Hello world!"},{"content":"I just got to make a bit of progress on building a technical blog which is something I started to think about a few years ago. Back at the beginning, the focus was on getting familiar with static site generators, mainly Jekyll and Hugo.\nNow, I\u0026rsquo;m going with Hugo for, mostly, simplicity:\nFeature Hugo 🏎️ Jekyll 📝 Performance ⚡ Extremely fast (built with Go) 🚶 Slower (built with Ruby) Installation ✅ Single binary, no dependencies ❌ Requires Ruby and Bundler Templates ⚠️ Uses Go templates (harder to learn) ✅ Uses Liquid templates (easier) Content Format ✅ Markdown, TOML/YAML/JSON ✅ Markdown, YAML Plugins ❌ No plugin system (built-in features only) ✅ Supports plugins for more functionality GitHub Pages ⚠️ Requires extra setup ✅ Natively supported Ease of Use ❌ Steeper learning curve ✅ Easier for beginners Best For 🚀 Speed, large sites, developers ✍️ Blogs, simple websites, GitHub Pages ","permalink":"https://danielpaval.github.io/posts/2025-03-01-hugo-vs-jekyll/","summary":"\u003cp\u003eI just got to make a bit of progress on building a technical blog which is something I started to think about a few years ago. Back at the beginning, the focus was on getting familiar with static site generators, mainly Jekyll and Hugo.\u003c/p\u003e\n\u003cp\u003eNow, I\u0026rsquo;m going with Hugo for, mostly, simplicity:\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003eFeature\u003c/th\u003e\n          \u003cth\u003eHugo 🏎️\u003c/th\u003e\n          \u003cth\u003eJekyll 📝\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003ePerformance\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003e⚡ Extremely fast (built with Go)\u003c/td\u003e\n          \u003ctd\u003e🚶 Slower (built with Ruby)\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eInstallation\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003e✅ Single binary, no dependencies\u003c/td\u003e\n          \u003ctd\u003e❌ Requires Ruby and Bundler\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eTemplates\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003e⚠️ Uses Go templates (harder to learn)\u003c/td\u003e\n          \u003ctd\u003e✅ Uses Liquid templates (easier)\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eContent Format\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003e✅ Markdown, TOML/YAML/JSON\u003c/td\u003e\n          \u003ctd\u003e✅ Markdown, YAML\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003ePlugins\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003e❌ No plugin system (built-in features only)\u003c/td\u003e\n          \u003ctd\u003e✅ Supports plugins for more functionality\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eGitHub Pages\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003e⚠️ Requires extra setup\u003c/td\u003e\n          \u003ctd\u003e✅ Natively supported\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eEase of Use\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003e❌ Steeper learning curve\u003c/td\u003e\n          \u003ctd\u003e✅ Easier for beginners\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003cstrong\u003eBest For\u003c/strong\u003e\u003c/td\u003e\n          \u003ctd\u003e🚀 Speed, large sites, developers\u003c/td\u003e\n          \u003ctd\u003e✍️ Blogs, simple websites, GitHub Pages\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e","title":"Hugo vs Jekyll"},{"content":"Elasticsearch Install Python Install uv: pip install uv Clone https://github.com/cr7258/elasticsearch-mcp-server Setup Claude uvx Setup { \u0026#34;mcpServers\u0026#34;: { \u0026#34;elasticsearch\u0026#34;: { \u0026#34;command\u0026#34;: \u0026#34;uvx\u0026#34;, \u0026#34;args\u0026#34;: [ \u0026#34;elasticsearch-mcp-server\u0026#34; ], \u0026#34;env\u0026#34;: { \u0026#34;ELASTIC_HOST\u0026#34;: \u0026#34;http://localhost:9200\u0026#34;, \u0026#34;ELASTIC_USERNAME\u0026#34;: \u0026#34;elastic\u0026#34;, \u0026#34;ELASTIC_PASSWORD\u0026#34;: \u0026#34;changeme\u0026#34; } } } } uv Setup { \u0026#34;mcpServers\u0026#34;: { \u0026#34;elasticsearch\u0026#34;: { \u0026#34;command\u0026#34;: \u0026#34;uv\u0026#34;, \u0026#34;args\u0026#34;: [ \u0026#34;--directory\u0026#34;, \u0026#34;C:\\\\Repositories\\\\mcp\\\\elasticsearch-mcp-server\u0026#34;, \u0026#34;run\u0026#34;, \u0026#34;elasticsearch-mcp-server\u0026#34; ], \u0026#34;env\u0026#34;: { \u0026#34;ELASTIC_HOST\u0026#34;: \u0026#34;http://localhost:9200\u0026#34;, \u0026#34;ELASTIC_USERNAME\u0026#34;: \u0026#34;elastic\u0026#34;, \u0026#34;ELASTIC_PASSWORD\u0026#34;: \u0026#34;changeme\u0026#34; } } } } File System Setup { \u0026#34;mcpServers\u0026#34;: { \u0026#34;filesystem\u0026#34;: { \u0026#34;command\u0026#34;: \u0026#34;npx\u0026#34;, \u0026#34;args\u0026#34;: [ \u0026#34;-y\u0026#34;, \u0026#34;@modelcontextprotocol/server-filesystem\u0026#34;, \u0026#34;C:\\\\Users\\\\dani\\\\Desktop\u0026#34; ] } } } Atlassian ","permalink":"https://danielpaval.github.io/posts/2025-02-28-anthropic-mcp/","summary":"\u003ch1 id=\"elasticsearch\"\u003eElasticsearch\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003eInstall Python\u003c/li\u003e\n\u003cli\u003eInstall \u003ccode\u003euv\u003c/code\u003e: \u003ccode\u003epip install uv\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eClone \u003ca href=\"https://github.com/cr7258/elasticsearch-mcp-server\"\u003ehttps://github.com/cr7258/elasticsearch-mcp-server\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eSetup Claude\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"uvx-setup\"\u003euvx Setup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;mcpServers\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;elasticsearch\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;command\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;uvx\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;args\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;elasticsearch-mcp-server\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;env\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ELASTIC_HOST\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://localhost:9200\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ELASTIC_USERNAME\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;elastic\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ELASTIC_PASSWORD\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;changeme\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"uv-setup\"\u003euv Setup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;mcpServers\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026#34;elasticsearch\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;command\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;uv\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;args\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;--directory\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;C:\\\\Repositories\\\\mcp\\\\elasticsearch-mcp-server\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;run\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;elasticsearch-mcp-server\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;env\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ELASTIC_HOST\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://localhost:9200\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ELASTIC_USERNAME\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;elastic\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003e\u0026#34;ELASTIC_PASSWORD\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;changeme\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"file-system\"\u003eFile System\u003c/h1\u003e\n\u003ch2 id=\"setup\"\u003eSetup\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;mcpServers\u0026#34;\u003c/span\u003e: {        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;filesystem\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;command\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;npx\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;args\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;-y\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@modelcontextprotocol/server-filesystem\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;C:\\\\Users\\\\dani\\\\Desktop\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"atlassian\"\u003eAtlassian\u003c/h1\u003e","title":"Anthropic Model Context Protocol (MCP)"},{"content":" ℹ️ This is a quick blog post to mainly play with Jekyll.\nNot long ago Windows on my laptop reported that Skype was last used on 1/1/1601.. While I rarely use Skype now-a-days, it surely wasn\u0026rsquo;t that long! January 1st does hint at some kind of a date baseline, just like the Unix epoch, but why 1601?\nOf course, this was a quick answer to look up and it turns out to be that \u0026ldquo;1601 was the first year of the 400-year Gregorian calendar cycle at the time Windows NT was made\u0026rdquo;1. More specifically, \u0026ldquo;The FILETIME structure records time in the form of 100-nanosecond intervals since January 1, 1601\u0026rdquo;2.\nWhile on the subject, it\u0026rsquo;s worth recalling that Unix time records 1-second intervals since January 1, 1970.\nActually, there seem to be a lot more such Epoch dates, not just the ubiquitous Unix and Windows ones.\nEpoch_(computing)#Notable_epoch_dates_in_computing\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nWhy is the Win32 epoch January 1, 1601?\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://danielpaval.github.io/posts/2022-06-18-win32-epoch/","summary":"\u003cblockquote\u003e\n\u003cp\u003eℹ️ This is a quick blog post to mainly play with Jekyll.\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003eNot long ago Windows on my laptop reported that Skype was last used on \u003cem\u003e1/1/1601\u003c/em\u003e.. While I rarely use Skype now-a-days, it surely wasn\u0026rsquo;t that long! January 1\u003c!-- raw HTML omitted --\u003est\u003c!-- raw HTML omitted --\u003e does hint at some kind of a date baseline, just like the Unix epoch, but why \u003cem\u003e1601\u003c/em\u003e?\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Image description\" loading=\"lazy\" src=\"/posts/2022-06-18-win32-epoch/win32-epoch-cleanup.png\"\u003e\u003c/p\u003e\n\u003cp\u003eOf course, this was a quick answer to look up and it turns out to be that \u003cem\u003e\u0026ldquo;1601 was the first year of the 400-year Gregorian calendar cycle at the time Windows NT was made\u0026rdquo;\u003c/em\u003e\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e. More specifically, \u003cem\u003e\u0026ldquo;The \u003ccode\u003eFILETIME\u003c/code\u003e structure records time in the form of 100-nanosecond intervals since January 1, 1601\u0026rdquo;\u003c/em\u003e\u003csup id=\"fnref:2\"\u003e\u003ca href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e2\u003c/a\u003e\u003c/sup\u003e.\u003c/p\u003e","title":"Win32 Epoch (1/1/1601)"}]