PowerDecisionDocs
Back to Wizard

PowerDecision User Guide

Decision Wizard

Overview

The Decision Wizard is a visual rule editor that allows business users to create decision models without writing code. It provides a step-by-step interface for defining inputs, outputs, rules, and conditions that are automatically converted to DMN format for execution.

Access: The Decision Wizard is available at /decision-wizard/wizard.html relative to the project root, or via the "Back to Wizard" link in the documentation header.

Wizard Workflow

The wizard guides you through a structured process to create decision models:

StepSectionWhat You Define
1Model InfoModel ID (unique identifier), name, description, and version
2InputsInput variables with name, data type (string, number, boolean, date), and optional allowed values
3OutputsOutput variables with name, data type, and optional allowed values
4Hit PolicyHow rules are matched: FIRST, UNIQUE, PRIORITY, ANY, or COLLECT
5RulesIndividual rules with conditions on inputs, output values, and optional priority/reason
6ReviewPreview the complete decision model and submit to the API

Features

  • Template loading — Start from any of the 7 pre-built templates (loan approval, credit limit, etc.)
  • Condition builder — Visual dropdowns for operators (equals, greater than, between, in list, etc.)
  • Multi-output support — Define multiple output columns per rule
  • Default rules — Add a catch-all rule that matches when no other rules do
  • JSON export — Download the model definition as JSON for version control
  • Direct upload — Submit the model directly to the PowerDecision API for immediate use
  • Validation — Real-time validation of inputs, outputs, and rule completeness

Hit Policy Auto-Correction: If you select UNIQUE hit policy but include a default rule (a rule with no conditions), the engine automatically switches to FIRST policy since UNIQUE requires exactly one match per input combination.

API Reference

All API endpoints are served on port 8031 by default. The base path for decision endpoints is /api/powerdecision/v1.

Submit Decision

Submit a decision request for asynchronous evaluation. Returns a job ID for polling.

PropertyValue
MethodPOST
Endpoint/api/powerdecision/v1/decisions
Content-Typeapplication/json

Request Body (DecisionSpec):

{
  "model_id": "loan_approval",
  "version": "1.0",
  "context": {
    "purpose": "Evaluate loan application"
  },
  "inputs": {
    "credit_score": 720,
    "annual_income": 85000,
    "loan_amount": 250000,
    "employment_status": "employed",
    "debt_to_income": 0.28,
    "loan_purpose": "home_purchase"
  }
}

Request Fields:

FieldTypeRequiredDescription
model_idstringYesIdentifier of the decision model to evaluate
versionstringNoModel version (defaults to latest)
contextobjectNoMetadata about the decision context
inputsobjectYesKey-value pairs matching the model's input schema

Response (202 Accepted):

{
  "jobId": "dec-a1b2c3d4",
  "status": "PENDING"
}

Error Response (400 Bad Request):

{
  "error": "Model not found: unknown_model"
}

Get Decision Result

Poll for the result of a submitted decision job.

PropertyValue
MethodGET
Endpoint/api/powerdecision/v1/decisions/{jobId}

Response (200 OK — completed):

{
  "model_id": "loan_approval",
  "version": "1.0",
  "status": "SUCCESS",
  "decision": {
    "approval_status": "approved",
    "max_loan_amount": 300000,
    "interest_rate": 4.5,
    "reason": "Good credit score with stable employment"
  },
  "explanation": "Rule 2 matched: credit_score >= 700 AND employment_status = employed",
  "metadata": {
    "evaluation_time_ms": 45,
    "hit_policy": "FIRST",
    "rules_evaluated": 5,
    "rules_matched": 1
  }
}

Response Fields:

FieldDescription
model_idThe model that was evaluated
versionModel version used
statusPENDING, PROCESSING, SUCCESS, or ERROR
decisionOutput values from the decision table (only when SUCCESS)
explanationHuman-readable explanation of which rules matched
metadataEvaluation statistics (time, rules evaluated, etc.)

Upload Model

Upload a decision model from wizard JSON. The JSON is validated, converted to DMN XML, and stored for evaluation.

PropertyValue
MethodPOST
Endpoint/api/powerdecision/v1/models/upload
Content-Typeapplication/json

Request Body:

{
  "model_id": "customer_risk",
  "name": "Customer Risk Assessment",
  "description": "Evaluates customer risk level based on profile data",
  "version": "1.0",
  "inputs_schema": [
    { "name": "account_age_months", "type": "number" },
    { "name": "transaction_count", "type": "number" },
    { "name": "country", "type": "string" }
  ],
  "outputs_schema": [
    { "name": "risk_level", "type": "string", "allowed_values": ["low", "medium", "high"] },
    { "name": "review_required", "type": "boolean" }
  ],
  "policy": "FIRST",
  "rules": [
    {
      "conditions": [
        { "input": "account_age_months", "operator": "lt", "value": 3 },
        { "input": "country", "operator": "in", "value": ["NG", "PH", "RO"] }
      ],
      "outputs": { "risk_level": "high", "review_required": true },
      "priority": 1,
      "reason": "New account from high-risk country"
    }
  ]
}

Response (200 OK):

{
  "model_id": "customer_risk",
  "version": "1.0",
  "status": "uploaded",
  "message": "Model uploaded and DMN generated successfully"
}

List Models

Returns all registered decision models (both built-in and uploaded).

PropertyValue
MethodGET
Endpoint/api/powerdecision/v1/models

Response (200 OK):

{
  "models": [
    {
      "model_id": "capacity_adjustment",
      "name": "Capacity Adjustment",
      "version": "1.0",
      "type": "builtin",
      "description": "Built-in capacity adjustment model"
    },
    {
      "model_id": "loan_approval",
      "name": "Loan Approval",
      "version": "1.0",
      "type": "runtime",
      "description": "Uploaded via wizard"
    }
  ],
  "count": 2
}

Health Endpoints

PowerDecision provides multiple health check endpoints for different orchestration needs:

EndpointTypeDescription
GET /q/healthQuarkus SmallRyeFull health check (liveness + readiness) with Quarkus standard format
GET /health/livenessCustomLightweight liveness probe — returns {"status": "UP"}
GET /health/readinessCustomReadiness probe — returns {"status": "UP"}
GET /q/health/liveQuarkus SmallRyeQuarkus-native liveness check
GET /q/health/readyQuarkus SmallRyeQuarkus-native readiness check

Orchestrator Integration: PowerOrchestrator uses the custom /health/liveness endpoint for health monitoring. The /q/health endpoints follow the Quarkus SmallRye Health standard and include additional subsystem checks.

Additional Development Endpoints:

EndpointDescription
GET /openapiOpenAPI 3.0 specification (JSON)
GET /swagger-ui.htmlInteractive Swagger UI for API exploration
GET /q/health-uiQuarkus Health UI dashboard

Model Management

Built-in Models

PowerDecision ships with pre-compiled DMN models that are available immediately without upload:

Model IDDescriptionType
capacity_adjustmentCapacity adjustment decision for the PDP pipelineBuilt-in (Kogito-compiled)

Built-in models are compiled into the application at build time via Kogito. They are evaluated through the Kogito runtime directly, which provides the fastest execution path.

Uploading Models

Models uploaded via the wizard or API go through this pipeline:

  1. Validation — The model_id is checked for uniqueness and format
  2. DMN GenerationDmnGenerator converts the JSON to DMN XML with FEEL expressions
  3. File Storage — The DMN XML is written to models/{model_id}.dmn
  4. Registry Update — Model metadata is stored in Redis for quick lookup
  5. Runtime Ready — The model is immediately available for evaluation via RuntimeDmnEvaluator

Runtime vs Built-in: Uploaded models use RuntimeDmnEvaluator (KIE container per evaluation), which is slightly slower than Kogito-compiled built-in models. For production-critical models, consider compiling them as Kogito resources.

Model Registry

The model registry uses Redis as the metadata store with filesystem as the source of truth for DMN files:

  • Redis — Stores model metadata (ID, name, version, type, timestamps)
  • Filesystem — Stores the actual DMN XML files in the models/ directory
  • Startup sync — On startup, the registry loads from Redis and scans the filesystem for orphaned DMN files not yet registered
  • Fallback — If Redis is unavailable, models are still loaded from the filesystem

Configuration

Environment Variables

PowerDecision is configured via Quarkus application properties and environment variables:

VariableDefaultDescription
QUARKUS_HTTP_PORT8031HTTP server port
QUARKUS_HTTP_CORStrueEnable CORS
QUARKUS_HTTP_CORS_ORIGINS*Allowed CORS origins
QUARKUS_REDIS_HOSTSredis://localhost:6379Redis connection URL
MODELS_PATHmodelsDirectory for DMN model files
JAVA_OPTSnoneJVM options (e.g., -Xmx512m)
QUARKUS_LOG_LEVELINFOApplication log level
QUARKUS_SMALLRYE_HEALTH_UI_ALWAYS_INCLUDEtrueEnable health UI
QUARKUS_SWAGGER_UI_ALWAYS_INCLUDEtrueEnable Swagger UI in production

CORS Configuration

CORS is enabled by default with permissive settings for development. For production, restrict origins:

# application.properties
quarkus.http.cors=true
quarkus.http.cors.origins=https://yourdomain.com,https://wizard.yourdomain.com
quarkus.http.cors.methods=GET,POST,PUT,DELETE,OPTIONS
quarkus.http.cors.headers=Content-Type,Authorization

Production: Replace the wildcard * origin with specific domains in production to prevent unauthorized cross-origin access.

Redis Configuration

Redis is used for the model registry metadata. If Redis is unavailable, the system falls back to filesystem-only mode.

# Default Redis configuration
quarkus.redis.hosts=redis://localhost:6379

# Docker Compose maps container port 6379 to host port 6381
# to avoid conflicts with other Redis instances
quarkus.redis.hosts=redis://redis:6379  # inside Docker network

Redis stores:

  • Model metadata (JSON hash per model_id)
  • Model version history
  • Registry index for fast model listing

Deployment

Docker

PowerDecision uses a multi-stage Docker build (Maven build → JRE 17 Alpine runtime):

# Build the image
docker build -t powerdecision-api ./decision-api

# Run standalone
docker run -d \
  --name powerdecision \
  -p 8031:8031 \
  -v $(pwd)/models:/app/models \
  -e QUARKUS_REDIS_HOSTS=redis://host.docker.internal:6379 \
  powerdecision-api

The Dockerfile uses a custom entrypoint that starts the Quarkus application with the -Dquarkus.http.host=0.0.0.0 flag to listen on all interfaces.

Docker Compose

The recommended way to run PowerDecision with its Redis dependency:

# Start all services
docker compose up -d

# View logs
docker compose logs -f decision-api

# Stop all services
docker compose down

The Docker Compose configuration includes:

ServiceImagePortDescription
decision-apiBuilt from Dockerfile8031:8031PowerDecision API server
redisredis:7-alpine6381:6379Model registry store

Persistent volumes:

  • ./models:/app/models — DMN model files (filesystem storage)
  • redis-data:/data — Redis persistence

Hetzner Cloud Deployment

For production deployment on Hetzner Cloud, refer to the Hetzner Deployment Guide in the project root. Key considerations for PowerDecision:

  • Memory — JVM-based application; allocate at least 512 MB for the container
  • Redis — Can share a Redis instance with other PowerTools products, but use a different database number
  • Models volume — Mount a persistent volume for the models/ directory to survive container restarts
  • Health checks — Use /health/liveness for Docker HEALTHCHECK and orchestrator monitoring
  • Reverse proxy — Expose through Traefik or nginx with TLS termination

Troubleshooting

ProblemCauseSolution
Model not found errorModel ID doesn't exist in registryCheck GET /models for available models. Upload the model first via wizard or API.
DMN generation failsInvalid wizard JSON schemaEnsure inputs_schema, outputs_schema, and rules follow the expected format. Check that all condition operators are valid.
UNIQUE policy auto-correctedDefault rule present with UNIQUE policyThis is expected behavior. UNIQUE requires exactly one match; default rules always match. Engine switches to FIRST automatically.
Job stuck in PROCESSINGDMN evaluation error or timeoutCheck application logs. Verify input types match the model's input schema. Ensure FEEL expressions are valid.
Redis connection refusedRedis not running or wrong portVerify Redis is running. Check QUARKUS_REDIS_HOSTS. Docker Compose maps port 6381→6379.
Model not available after restartRedis data lost, no filesystem backupEnsure Redis persistence is enabled or models are stored on a persistent volume. On startup, the registry scans the filesystem for orphaned DMN files.
CORS errors from wizardOrigins not configuredSet QUARKUS_HTTP_CORS_ORIGINS to include the wizard's origin. Default is * (all origins).
Swagger UI not loadingDisabled in production modeSet quarkus.swagger-ui.always-include=true in application.properties or environment.
OutOfMemoryErrorJVM heap too small for many modelsIncrease heap with JAVA_OPTS=-Xmx1g. Each RuntimeDmnEvaluator creates a KIE container.
Evaluation returns empty decisionNo rules matched the inputsAdd a default rule (no conditions) as a catch-all. Check that FEEL expressions match your input values.