# API7 Enterprise Edition Demo A comprehensive demo platform showcasing **API7 Enterprise Edition** (API7EE) as an API Gateway with two FastAPI microservices: a **Web frontend** with embedded documentation and an **API backend** with LLM integration. Features automated CI/CD via Gitea Actions, Helm-based deployment, and advanced API7 Gateway configurations including AI rate limiting. ## πŸ“‹ Table of Contents - [Overview](#overview) - [Architecture](#architecture) - [Project Structure](#project-structure) - [Features](#features) - [Quick Start](#quick-start) - [CI/CD Pipeline](#cicd-pipeline) - [Kubernetes Deployment](#kubernetes-deployment) - [API7 Gateway Configuration](#api7-gateway-configuration) - [Development](#development) - [Troubleshooting](#troubleshooting) - [Resources](#resources) ## 🎯 Overview This project demonstrates enterprise-grade API Gateway patterns using **API7 Enterprise Edition**, showcasing: - **Microservices Architecture**: Web frontend + API backend - **AI Integration**: LLM endpoints with OpenAI-compatible API - **Advanced Rate Limiting**: Token-based AI rate limiting + IP-based rate limiting - **Service Discovery**: Kubernetes-native service discovery via API7 - **Automated Deployment**: Gitea Actions CI/CD + Helm charts - **Production-Ready**: TLS, monitoring, autoscaling, and security policies **Live Demo**: `https://api7-demo.commandware.it` ## πŸ—οΈ Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Internet / Users β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ NGINX Ingress Controller (TLS) β”‚ β”‚ cert-manager (Let's Encrypt) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ API7 Enterprise Gateway β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Routes & Plugins: β”‚ β”‚ β”‚ β”‚ β€’ / β†’ Web Service (Apache/Nginx) β”‚ β”‚ β”‚ β”‚ β€’ /api β†’ API Backend (Rate: 100 req/60s) β”‚ β”‚ β”‚ β”‚ β€’ /api/llm β†’ LLM Endpoints (Rate: 100 tokens/60s) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β–Ό β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Web Service β”‚ β”‚ API Service β”‚ β”‚ (apache/nginx) β”‚ β”‚ (nginx) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Frontend UI β”‚ β”‚ β€’ REST API β”‚ β”‚ β€’ Documentation β”‚ β”‚ β€’ LLM Integration β”‚ β”‚ β€’ API Proxy β”‚ β”‚ β€’ Swagger Docs β”‚ β”‚ Replicas: 2-10 β”‚ β”‚ Replicas: 3-20 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Open WebUI (LLM) β”‚ β”‚ OpenAI-Compatible β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Service Naming **Important**: The Helm chart names services as `apache-service` and `nginx-service` for API7 routing: - **Web Service**: Deployed as `apache-service` (serves frontend and docs) - **API Service**: Deployed as `nginx-service` (serves REST API and LLM endpoints) This naming convention is used in ADC configuration for consistent routing. ## πŸ“ Project Structure ``` api7ee/ β”œβ”€β”€ web/ # Web frontend application β”‚ β”œβ”€β”€ main.py # FastAPI app with templates & API proxy β”‚ β”œβ”€β”€ Dockerfile # Multi-stage build with MkDocs β”‚ β”œβ”€β”€ requirements.txt # Dependencies: fastapi, httpx, mkdocs β”‚ β”œβ”€β”€ templates/ # Jinja2 HTML templates β”‚ β”‚ β”œβ”€β”€ base.html # Base template β”‚ β”‚ β”œβ”€β”€ index.html # Dashboard β”‚ β”‚ β”œβ”€β”€ items.html # Items page β”‚ β”‚ β”œβ”€β”€ users.html # Users page β”‚ β”‚ └── llm.html # LLM chat interface β”‚ β”œβ”€β”€ static/ # CSS and JavaScript assets β”‚ β”œβ”€β”€ docs/ # MkDocs documentation source β”‚ β”‚ β”œβ”€β”€ index.md β”‚ β”‚ β”œβ”€β”€ getting-started.md β”‚ β”‚ β”œβ”€β”€ architecture.md β”‚ β”‚ β”œβ”€β”€ api7-configuration.md β”‚ β”‚ β”œβ”€β”€ kubernetes-resources.md β”‚ β”‚ β”œβ”€β”€ cicd-pipeline.md β”‚ β”‚ └── troubleshooting.md β”‚ └── mkdocs.yml # MkDocs configuration β”œβ”€β”€ api/ # API backend application β”‚ β”œβ”€β”€ main.py # FastAPI app with REST + LLM endpoints β”‚ β”œβ”€β”€ Dockerfile # Container image β”‚ β”œβ”€β”€ requirements.txt # Dependencies: fastapi, httpx, pydantic β”‚ └── db.json # Sample data file β”œβ”€β”€ helm/ # Helm chart for Kubernetes β”‚ └── api7ee-demo-k8s/ β”‚ β”œβ”€β”€ Chart.yaml # Chart metadata (v0.1.0) β”‚ β”œβ”€β”€ values.yaml # Default configuration β”‚ β”œβ”€β”€ values-dev.yaml # Development overrides β”‚ β”œβ”€β”€ values-production.yaml # Production overrides β”‚ └── templates/ # Kubernetes manifests β”‚ β”œβ”€β”€ deployment-web.yaml β”‚ β”œβ”€β”€ deployment-api.yaml β”‚ β”œβ”€β”€ service-web.yaml β”‚ β”œβ”€β”€ service-api.yaml β”‚ β”œβ”€β”€ ingress.yaml β”‚ β”œβ”€β”€ configmap-adc.yaml # API7 ADC configuration β”‚ β”œβ”€β”€ job-adc-sync.yaml # ADC sync job β”‚ β”œβ”€β”€ certificate.yaml # cert-manager certificate β”‚ β”œβ”€β”€ hpa-web.yaml # Horizontal Pod Autoscaler β”‚ β”œβ”€β”€ hpa-api.yaml β”‚ └── ... β”œβ”€β”€ .gitea/ β”‚ └── workflows/ β”‚ β”œβ”€β”€ build.yml # Docker image builds β”‚ └── helm-build.yml # Helm chart packaging β”œβ”€β”€ adc.yaml # Standalone API7 ADC configuration └── README.md # This file ``` ## ✨ Features ### Web Application (`web/`) - **Interactive Dashboard**: Modern UI with real-time stats - **Embedded Documentation**: MkDocs Material theme at `/docs` - **API Proxy**: Proxies requests to API backend - **LLM Chat Interface**: Chat with videogame expert AI - **Health Checks**: `/health` endpoint - **Static Assets**: Custom CSS and JavaScript ### API Application (`api/`) - **REST API**: Items and Users CRUD operations - **LLM Integration**: OpenAI-compatible chat endpoint - **Swagger Documentation**: Auto-generated at `/docs` - **Data Validation**: Pydantic models - **Health Endpoints**: `/health` and `/llm/health` - **Model Management**: `/llm/models` endpoint ### API7 Gateway Features - **Advanced Rate Limiting**: - Standard: 100 requests/60s per IP for `/api/*` - AI: 100 tokens/60s for `/api/llm/*` (token-based) - **Service Discovery**: Kubernetes-native discovery - **TLS/SSL**: Automatic certificate management - **HTTP β†’ HTTPS Redirect**: Enforced on all routes - **Prometheus Metrics**: Built-in monitoring - **Route Prioritization**: LLM routes (priority 20) > API (10) > Web (1) ### DevOps Features - **CI/CD**: Gitea Actions for automated builds - **Helm Packaging**: Automated chart publishing - **Horizontal Autoscaling**: HPA for both services - **Pod Disruption Budgets**: High availability - **Security**: Non-root containers, read-only root filesystem - **Multi-Environment**: Dev and production value files ## πŸš€ Quick Start ### Prerequisites - Docker (for local development) - Kubernetes cluster (v1.19+) - Helm 3.8.0+ - API7 Enterprise Edition installed - kubectl configured ### Local Development #### Run Web Application ```bash cd web pip install -r requirements.txt # Set API backend URL (optional) export API_BASE_URL="http://localhost:8001" python main.py ``` Access: - Dashboard: http://localhost:8000 - Documentation: http://localhost:8000/docs #### Run API Application ```bash cd api pip install -r requirements.txt # Configure LLM endpoint (optional) export OPENAI_API_BASE="http://localhost:11434/api" export OPENAI_API_KEY="your-api-key" export DEFAULT_LLM_MODEL="videogame-expert" python main.py ``` Access: - API Docs: http://localhost:8001/docs - Health: http://localhost:8001/health ### Docker Development ```bash # Build images docker build -t web-app ./web docker build -t api-app ./api # Run containers docker run -d -p 8000:8000 --name web web-app docker run -d -p 8001:8001 --name api api-app # With environment variables docker run -d -p 8001:8001 \ -e OPENAI_API_BASE="http://host.docker.internal:11434/api" \ -e OPENAI_API_KEY="sk-xxx" \ --name api api-app ``` ## πŸ”„ CI/CD Pipeline ### Docker Image Builds **Workflow**: `.gitea/workflows/build.yml` **Triggers**: - Push to any branch - Pull requests - Manual dispatch **Process**: 1. Checkout code 2. Set up Docker Buildx 3. Login to Gitea container registry 4. Build and push images: - `git.commandware.com/demos/api7-demo/web:` - `git.commandware.com/demos/api7-demo/api:` ### Helm Chart Publishing **Workflow**: `.gitea/workflows/helm-build.yml` **Triggers**: - Push to `main` branch (publishes) - Pull requests (lint only) - Manual dispatch **Process**: 1. Extract version from `Chart.yaml` 2. Lint Helm chart 3. Update image registries in values 4. Package chart as `.tgz` 5. Push to Gitea Helm registry: `https://git.commandware.com/api/packages/demos/helm` **Chart Versioning**: Version is defined in `helm/api7ee-demo-k8s/Chart.yaml` (single source of truth) ### Setup CI/CD 1. **Create Gitea Secrets**: ``` Repository Settings β†’ Secrets β†’ Add Secret - Name: USERNAME - Value: your-gitea-username - Name: TOKEN - Value: ``` 2. **Generate Token**: - User Settings β†’ Applications β†’ Generate New Token - Scopes: `write:package`, `read:package` 3. **Push to Trigger**: ```bash git push origin main ``` ## ☸️ Kubernetes Deployment ### Using Helm (Recommended) #### Add Helm Repository ```bash # Add the Helm repository helm repo add api7ee https://git.commandware.com/api/packages/demos/helm # Update repositories helm repo update # Search for available versions helm search repo api7ee ``` #### Install ```bash # Install with default values helm install api7ee-demo api7ee/api7ee-demo-k8s \ --namespace api7ee \ --create-namespace # Install with custom values helm install api7ee-demo api7ee/api7ee-demo-k8s \ --namespace api7ee \ -f custom-values.yaml # Install specific version with custom image tags helm install api7ee-demo api7ee/api7ee-demo-k8s \ --version 0.1.0 \ --set web.image.tag=main \ --set api.image.tag=main \ --set api7.gateway.adminKey="your-admin-key" \ --namespace api7ee ``` #### Configuration Key values to customize: ```yaml # Custom domain api7: hosts: - your-domain.com # API7 Gateway connection api7: gateway: adminUrl: http://api7ee3-0-xxx-dp-manager.api7ee.svc.cluster.local:7900 adminKey: "your-admin-key" gatewayService: gateway-0-xxx-gateway # Image tags web: image: tag: "v1.0.0" api: image: tag: "v1.0.0" # Scaling web: replicaCount: 3 api: replicaCount: 5 autoscaling: enabled: true maxReplicas: 30 # TLS api7: tls: certManager: enabled: true issuer: cloudflare-acme-prod ``` #### Manage Deployment ```bash # Check status helm list -n api7ee kubectl get pods -n api7ee # Upgrade helm upgrade api7ee-demo api7ee/api7ee-demo-k8s \ --namespace api7ee \ --reuse-values \ --set api.replicaCount=5 # Rollback helm rollback api7ee-demo -n api7ee # Uninstall helm uninstall api7ee-demo -n api7ee ``` ### Using Local Helm Chart ```bash # Install from local directory helm install api7ee-demo ./helm/api7ee-demo-k8s \ --namespace api7ee \ --create-namespace # Use production values helm install api7ee-demo ./helm/api7ee-demo-k8s \ -f ./helm/api7ee-demo-k8s/values-production.yaml \ --namespace api7ee ``` ### Environment-Specific Deployments **Development**: ```bash helm install api7ee-dev ./helm/api7ee-demo-k8s \ -f ./helm/api7ee-demo-k8s/values-dev.yaml \ --namespace api7ee-dev ``` **Production**: ```bash helm install api7ee-prod ./helm/api7ee-demo-k8s \ -f ./helm/api7ee-demo-k8s/values-production.yaml \ --namespace api7ee-prod ``` ## πŸ”Œ API7 Gateway Configuration ### ADC (API7 Declarative CLI) Configuration The Helm chart automatically configures API7 Gateway using ADC. Configuration is in `helm/api7ee-demo-k8s/templates/configmap-adc.yaml`. #### Route Structure **1. Web Route** (Priority: 1) ```yaml - name: apache-route uris: [/*] vars: - [uri, "~~", "^(?!/api)"] # Match all except /api/* plugins: redirect: http_to_https: true ``` **2. API Route** (Priority: 10) ```yaml - name: nginx-api-route uris: [/api, /api/*] plugins: redirect: http_to_https: true limit-count: count: 100 time_window: 60 key_type: "var" key: "remote_addr" ``` **3. LLM Route** (Priority: 20) ```yaml - name: nginx-api-llm-route uris: [/api/llm, /api/llm/*] plugins: redirect: http_to_https: true ai-rate-limiting: limit: 100 time_window: 60 limit_strategy: "total_tokens" ``` ### Manual ADC Sync If you need to manually sync ADC configuration: ```bash # Using standalone adc.yaml file adc sync -f adc.yaml \ --backend api7ee \ --server https://api7-dashboard.commandware.it \ --token \ --gateway-group default \ --tls-skip-verify # Publish routes via Dashboard # Navigate to: Services β†’ Routes β†’ Click "Publish" β†’ Select "default" gateway group ``` ### Service Discovery API7 automatically discovers Kubernetes services: ```yaml upstream: type: roundrobin discovery_type: kubernetes # Helm uses direct node configuration nodes: - host: apache-service.api7ee.svc.cluster.local port: 80 weight: 100 ``` When pods scale, API7 automatically updates the upstream nodes. ### Rate Limiting Configuration **Standard Rate Limiting** (IP-based): - Plugin: `limit-count` - Limit: 100 requests per 60 seconds per IP - Applies to: `/api/*` routes (excluding `/api/llm/*`) **AI Rate Limiting** (Token-based): - Plugin: `ai-rate-limiting` - Limit: 100 tokens per 60 seconds - Strategy: `total_tokens` (counts input + output tokens) - Applies to: `/api/llm/*` routes ### TLS/SSL Configuration **Option 1: cert-manager** (Recommended) ```yaml api7: tls: certManager: enabled: true issuer: cloudflare-acme-prod issuerKind: ClusterIssuer ``` **Option 2: Existing Secret** ```yaml api7: tls: enabled: true secretName: my-tls-secret ``` **Option 3: Direct Certificates** (Not recommended for production) ```yaml api7: tls: enabled: true certificate: | -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- key: | -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY----- ``` ## πŸ› οΈ Development ### Environment Variables **Web Application**: ```bash API_BASE_URL=http://localhost:8001 # API backend URL ``` **API Application**: ```bash OPENAI_API_BASE=http://localhost:11434/api # LLM API endpoint OPENAI_API_KEY=your-api-key # LLM API key DEFAULT_LLM_MODEL=videogame-expert # Default model ``` ### Testing Endpoints ```bash # Web health curl http://localhost:8000/health # API health curl http://localhost:8001/health # LLM health curl http://localhost:8001/llm/health # Get items curl http://localhost:8001/items # LLM chat curl -X POST http://localhost:8001/llm/chat \ -H "Content-Type: application/json" \ -d '{ "prompt": "What is Zelda?", "max_tokens": 150, "model": "videogame-expert" }' ``` ### Building Documentation ```bash cd web # Serve documentation locally mkdocs serve # Build static site mkdocs build -d site ``` ## πŸ”§ Troubleshooting ### Common Issues #### 1. Routes Return 404 **Symptom**: Routes synced but returning 404 **Cause**: Routes not published to gateway group **Solution**: ```bash # Check route status in API7 Dashboard # Services β†’ Select service β†’ Routes β†’ Check publication status # Publish via Dashboard: # Click "Publish" β†’ Select "default" gateway group β†’ Confirm # Or enable autoPublish in Helm: api7: autoPublish: true ``` #### 2. ADC Sync Job Fails **Symptom**: ADC sync job shows error status **Check logs**: ```bash kubectl logs -n api7ee -l app.kubernetes.io/component=adc-sync # Common issues: # - Incorrect adminKey # - Wrong adminUrl (should point to dp-manager service) # - Network connectivity to API7 Gateway ``` **Verify API7 connection**: ```bash # Test API7 admin API kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \ curl -H "X-API-KEY: your-admin-key" \ http://api7ee3-0-xxx-dp-manager.api7ee.svc.cluster.local:7900/apisix/admin/routes ``` #### 3. Service Discovery Not Working **Check**: ```bash # Verify service exists kubectl get svc -n api7ee apache-service nginx-service # Check service endpoints kubectl get endpoints -n api7ee # Verify service has named ports kubectl get svc apache-service -n api7ee -o yaml | grep -A5 ports ``` **Ensure ports are named**: ```yaml spec: ports: - port: 80 targetPort: 8000 name: http # ← Name is required ``` #### 4. LLM Endpoints Failing **Check API configuration**: ```bash # Verify environment variables kubectl get deployment nginx-service -n api7ee -o yaml | grep -A10 env # Check API logs kubectl logs -n api7ee -l app=nginx-service --tail=50 # Test LLM backend directly curl http://localhost:11434/api/chat/completions \ -H "Authorization: Bearer your-key" \ -d '{"model":"videogame-expert","messages":[{"role":"user","content":"test"}]}' ``` #### 5. Image Pull Errors **Solution**: ```bash # Create registry secret kubectl create secret docker-registry gitea-registry \ --docker-server=git.commandware.com \ --docker-username= \ --docker-password= \ -n api7ee # Add to Helm values global: imagePullSecrets: - name: gitea-registry ``` #### 6. Certificate Issues **Check cert-manager**: ```bash # Check certificate status kubectl get certificate -n api7ee # Check certificate details kubectl describe certificate api7ee-tls -n api7ee # Check cert-manager logs kubectl logs -n cert-manager -l app=cert-manager --tail=50 # Check challenge status (for ACME) kubectl get challenge -n api7ee ``` ### Getting Help 1. **Check logs**: ```bash kubectl logs -n api7ee -l app.kubernetes.io/name=api7ee-demo-k8s --tail=100 ``` 2. **Check events**: ```bash kubectl get events -n api7ee --sort-by='.lastTimestamp' ``` 3. **Verify Helm installation**: ```bash helm status api7ee-demo -n api7ee helm get values api7ee-demo -n api7ee ``` 4. **Test connectivity**: ```bash kubectl run -it --rm debug --image=nicolaka/netshoot --restart=Never -n api7ee -- bash # Inside pod: curl http://apache-service curl http://nginx-service ``` ## πŸ“š Resources ### Documentation - **API7 Enterprise**: https://docs.api7.ai/ - **APISIX**: https://apisix.apache.org/docs/ - **FastAPI**: https://fastapi.tiangolo.com/ - **Helm**: https://helm.sh/docs/ - **Gitea Actions**: https://docs.gitea.com/usage/actions/overview ### Project Links - **Repository**: https://git.commandware.com/demos/api7-demo - **Helm Registry**: https://git.commandware.com/api/packages/demos/helm - **Container Registry**: https://git.commandware.com/demos/-/packages/container - **Live Demo**: https://api7-demo.commandware.it ### Support - **Issues**: https://git.commandware.com/demos/api7-demo/issues - **Email**: support@commandware.com ## πŸ“„ License Demo project for API7 Enterprise Gateway evaluation. --- **Version**: 0.1.0 | **Last Updated**: 2025-10-07