Microservices Architecture
FlowPilot implements a microservices architecture with clear separation of concerns. Each service has a specific responsibility and communicates via REST APIs defined using OpenAPI.
Service Overview
| Service | Port | Type | Purpose |
|---|---|---|---|
| flowpilot-authz-api | 8002 | PDP | Authorization decisions |
| flowpilot-domain-services-api | 8003 | PEP | Workflow management |
| flowpilot-ai-agent-api | 8004 | PEP | AI agent execution |
| flowpilot-delegation-api | 8005 | PIP | Delegation graph |
| Firebase Authentication | - | IdP | Identity provider |
| OPA | 8181 | PDP | Policy engine |
Communication Patterns
All services communicate through REST APIs:
- Protected by TLS - All inter-service communication uses TLS
- Bearer token authentication - JWT validation on all protected endpoints
- Input sanitization - All inputs validated before processing
- Fail-closed - Services deny by default
Service Details
1. flowpilot-authz-api (Port 8002)
Role: Policy Decision Point (PDP) and Authorization Façade
Responsibilities:
- Accepts AuthZEN-compliant authorization requests
- Validates bearer tokens via JWKS
- Enforces delegation by calling delegation-api (ReBAC)
- Evaluates ABAC policies via OPA
- Returns structured authorization decisions with reason codes
Key Endpoints:
POST /v1/evaluate- Evaluate authorization requestGET /health- Health check
Code Structure:
authz-api/
├── main.py # FastAPI app and routes
├── core.py # Authorization logic
└── Dockerfile # Container definition
Key Files:
main.py- FastAPI application and route definitionscore.py- Core authorization logic and OPA integration
Environment Variables:
OPA_URL=http://opa:8181
DELEGATION_API_BASE_URL=http://flowpilot-delegation-api:8000
KEYCLOAK_JWKS_URI=https://keycloak:8443/realms/flowpilot/protocol/openid-connect/certs
2. flowpilot-delegation-api (Port 8005)
Role: Policy Information Point (PIP) for ReBAC
Responsibilities:
- Manages delegation relationships (principal → delegate)
- Resolves delegation chains (transitive)
- Validates delegation scope and actions
- SQLite-backed persistence
- No policy logic - purely relationship management
- No PII - only pseudonymous identifiers
Key Endpoints:
POST /v1/delegations- Create delegationGET /v1/delegations- List delegationsGET /v1/delegations/{id}- Get delegation detailsDELETE /v1/delegations/{id}- Revoke delegationPOST /v1/delegations/validate- Validate delegation chainGET /health- Health check
Code Structure:
delegation-api/
├── main.py # FastAPI app and routes
├── core.py # Delegation logic
└── Dockerfile # Container definition
Data Model:
Delegations are stored as directional edges in a graph:
principal_id- Who is delegatingdelegate_id- Who is being delegated toworkflow_id- Optional workflow scopescope- Actions granted (e.g.,["read", "execute"])created_at- Timestampexpires_at- Optional expiry
Delegation Chains:
Transitive delegation is supported:
- A delegates to B
- B delegates to C
- C can act on behalf of A (if scope permits)
- Chain length is bounded to prevent privilege amplification
3. flowpilot-domain-services-api (Port 8003)
Role: Policy Enforcement Point (PEP) for Workflow Domain
Responsibilities:
- Creates and manages workflows (trips)
- Creates and manages workflow items (booking steps)
- System of record for travel booking workflows
- Calls authz-api for all authorization checks
- Auto-creates delegations when workflows are created
Key Endpoints:
POST /v1/workflows- Create workflowGET /v1/workflows- List workflowsGET /v1/workflows/{id}- Get workflow detailsPOST /v1/workflows/{id}/items- Create workflow itemGET /v1/workflows/{id}/items- List workflow itemsGET /health- Health check
Code Structure:
domain-services-api/
├── main.py # FastAPI app and routes
├── core.py # Domain logic
└── Dockerfile # Container definition
Authorization Pattern:
Every operation calls authz-api:
authz_request = {
"subject": {"id": user_sub},
"action": {"name": "create"},
"resource": {
"type": "workflow",
"id": workflow_id
},
"context": {"principal": {"id": user_sub}}
}
response = requests.post(
f"{AUTHZ_BASE_URL}/v1/evaluate",
json=authz_request,
headers={"Authorization": f"Bearer {token}"}
)
if not response.json()["decision"]:
raise HTTPException(status_code=403, detail="Forbidden")
4. flowpilot-ai-agent-api (Port 8004)
Role: Policy Enforcement Point (PEP) for AI Agent Execution
Responsibilities:
- Executes workflow items on behalf of users
- Demonstrates agentic authorization patterns
- Service-to-service authentication using client credentials
- Calls authz-api before every execution
Key Endpoints:
POST /v1/execute- Execute workflow itemGET /health- Health check
Code Structure:
Service Account:
- Client ID:
flowpilot-agent - Uses client credentials flow
- Acts as
agent-runnerwith personaai-agent
5. OPA (Port 8181)
Role: Policy Decision Point (PDP) for ABAC
Responsibilities:
- Evaluates Rego policies
- Stateless decision engine
- Policies mounted from filesystem
- Hot-reload capability (restart recommended)
Key Endpoints:
POST /v1/data/auto_book/allow- Evaluate auto-book policyGET /health- Health checkGET /v1/policies- List loaded policies
Policies:
Located in infra/opa/policies/:
auto_book.rego- Autonomous booking policy
Policy Structure:
Updating Policies:
# Edit policy
vim infra/opa/policies/auto_book.rego
# Restart OPA to reload
docker compose restart opa
6. Firebase Authentication
Role: Identity Provider (IdP) - Fully managed by Google
Responsibilities:
- Issues Firebase ID tokens (JWTs)
- Manages users and authentication
- Provides email/password authentication
- Supports multiple sign-in methods
- Automatic token refresh
- Built-in email verification and password reset
Firebase Project: vision-course-476214
Authentication Methods:
- Email/Password - Primary method for users
- Built-in validation
- Password reset flows
-
Email verification
-
Service Accounts - For service-to-service auth
- Google Cloud identity tokens
- Automatic on Cloud Run
Key Endpoints:
- Auth REST API:
https://identitytoolkit.googleapis.com/v1/ - Token verification: Firebase Admin SDK (no endpoint)
User Data:
- Firebase Auth: Core identity (
uid,email,displayName) - Firestore: User profiles and preferences (
userscollection)
Shared Libraries
All services use shared libraries for common functionality:
Location: flowpilot-services/shared-libraries/
Libraries:
- security.py - JWT validation, input sanitization, security headers
- api_logging.py - Structured API logging
- profile.py - User profile management
- utils.py - General utilities
IMPORTANT: Shared libraries are copied into containers at build time. Changes require rebuilding all affected services:
Service Communication Flow
Workflow Creation Flow
- Client → domain-services-api:
POST /v1/workflows - domain-services-api → authz-api: Validate authorization
- authz-api validates JWT: Using Firebase Admin SDK (local validation)
- authz-api → delegation-api: Check delegation (if needed)
- authz-api → OPA: Evaluate policy
- authz-api → domain-services-api: Return decision
- domain-services-api → delegation-api: Create delegation
- domain-services-api → Client: Return workflow
AI Agent Execution Flow
- ai-agent-api gets service token: Google Cloud identity token (automatic on Cloud Run)
- ai-agent-api → domain-services-api: Get workflow item details
- ai-agent-api → authz-api: Request authorization
- authz-api → delegation-api: Validate delegation chain
- authz-api → OPA: Evaluate auto-book policy
- authz-api → ai-agent-api: Return decision
- ai-agent-api: Execute or deny based on decision
API Documentation
OpenAPI specifications are available in flowpilot-openapi/:
authz.openapi.yaml- Authorization APIdelegation.openapi.yaml- Delegation APIdomain-services.openapi.yaml- Workflow APIai-agent.openapi.yaml- AI Agent APIuser-profile.openapi.yaml- User Profile API
View these specs using Swagger Editor, Postman, or the embedded Swagger UI in the documentation site.
Container Platform
All services are containerized using Docker:
- Base images: Python 3.11+ slim images
- Platform: Some services specify
linux/amd64for compatibility - Networking: Services communicate via Docker network
- Volumes: Persistent data stored in Docker volumes
Development Workflow
Rebuilding a Service
# Rebuild specific service
docker compose up -d --build flowpilot-authz-api
# View logs
docker compose logs -f flowpilot-authz-api
Rebuilding All Services
Testing Service Health
# Test all health endpoints
for port in 8002 8003 8004 8005; do
curl -s http://localhost:$port/health | jq
done
Production Considerations
Scalability
- All services are stateless (except delegation-api SQLite)
- Can be horizontally scaled behind load balancers
- OPA is fully stateless and horizontally scalable
- Consider moving delegation-api to PostgreSQL for production
High Availability
- Deploy multiple instances of each service
- Use managed OIDC provider (or HA Keycloak cluster)
- Use managed OPA deployment
- Implement circuit breakers for inter-service calls
Monitoring
- All services expose
/healthendpoints - Structured logging via
api_logging.py - Consider adding:
- Prometheus metrics endpoints
- Distributed tracing (OpenTelemetry)
- Centralized logging (ELK, Splunk)
Security
- Use proper TLS certificates (not mkcert)
- Rotate secrets regularly
- Enable audit logging
- Set
INCLUDE_ERROR_DETAILS=0 - Use managed secret storage (e.g., GCP Secret Manager)