Public documentation for governed AI labor
SDKs/Governance/Connectors
Arx / Docs / Mendix ARX Module Design

Documentation

Mendix ARX Module Design

arxsec-site / examples/mendix-integration-module.md

arxsec-site repo-root examples/mendix-integration-module.md

Overview

The ARX Mendix Module is a reusable package that abstracts ARX REST API integration for Mendix developers. It provides pre-built microflows, widgets, and utilities for policy enforcement, operation execution, and audit logging.

Architecture

`` Mendix Application ↓ [ArxPolicy_Checker Microflow] ← Check if operation allowed ↓ [Policy Result: PERMIT/ESCALATE/DENY] ↓ If DENY: Raise exception / show error If ESCALATE: Route to approval workflow If PERMIT: Continue to execution ↓ [ArxOperation_Execute Microflow] ← Execute operation with governance ↓ [Audit Log Entry] ← Stored in ARX backend ↓ [ArxAuditLog_Widget] ← Display history and compliance ``

Core Components

1. Policy Evaluation (ArxPolicy_Checker)

Purpose: Evaluate if an operation is allowed by policy without executing it.

Parameters:

  • Connector (String): Connector name (e.g., "okta", "crowdstrike")
  • Operation (String): Operation name (e.g., "users:deactivate")
  • Parameters (JSON): Operation parameters

Returns:

  • Verdict (String): "PERMIT", "ESCALATE", or "DENY"
  • RiskScore (Integer): 0-100 risk assessment
  • PolicyId (String): Policy that generated verdict
  • Message (String): Human-readable explanation
  • RequiresApproval (Boolean): Whether approval is needed

HTTP Call: ``` POST /v1/lowcode/policy-check Authorization: Bearer {API_KEY}

{ "connector": "okta", "operation": "users:deactivate", "params": {"user_id": "user@example.com"} } ```

Response Handler:

  • Parse JSON response
  • Extract verdict and risk_score
  • Store in response entity

2. Operation Execution (ArxOperation_Execute)

Purpose: Execute a security operation with automatic policy enforcement, audit logging, and optional approval.

Parameters:

  • Connector (String)
  • Operation (String)
  • Parameters (JSON)
  • RequireApproval (Boolean): Force approval requirement
  • UserContext (JSON): Metadata for audit (app_name, user_id, etc.)

Returns:

  • Success (Boolean)
  • Result (JSON): Operation result
  • Error (String): Error message if failed
  • AuditId (String): Audit log entry ID
  • Verdict (String): Policy verdict
  • RiskScore (Integer)
  • RequiresApproval (Boolean)

HTTP Call: ``` POST /v1/lowcode/execute Authorization: Bearer {API_KEY}

{ "connector": "crowdstrike", "operation": "hosts:read", "params": {"hostname": "prod-server-01"}, "require_approval": false, "user_context": {"app_name": "Security Dashboard", "user_id": "user123"} } ```

Error Handling:

  • Catch HTTP errors (401, 403, 404, 500)
  • Log errors to Mendix logging
  • Return error response to caller
  • Store failed operation in audit log

3. Audit Log Display (ArxAuditLog_Widget)

Purpose: Display and filter operation history with policy verdicts and risk scores.

Features:

  • DataGrid showing operation history
  • Filter by:
  • Connector
  • Operation
  • Verdict (PERMIT/ESCALATE/DENY)
  • Risk level (LOW/MEDIUM/HIGH/CRITICAL)
  • Date range
  • User
  • Export to CSV/PDF
  • Risk color coding (green/yellow/red)

Data Attributes:

  • audit_id (String)
  • connector (String)
  • operation (String)
  • verdict (String)
  • risk_score (Integer)
  • user_id (String)
  • timestamp (DateTime)
  • result (JSON)

Implementation Details

REST Client Configuration

Create a dedicated HTTP Client in Mendix for ARX calls:

``xml <httpClient> <name>ARXSecurityAPI</name> <baseUrl>https://api.arxsec.io</baseUrl> <timeout>30000</timeout> <defaultHeaders> <header name="Authorization" value="Bearer {ArxSecurityAPI_Key}"/> <header name="Content-Type" value="application/json"/> </defaultHeaders> <errorHandling> <handler statusCode="401"> <log level="ERROR" message="Unauthorized: Check API key"/> </handler> <handler statusCode="403"> <log level="ERROR" message="Forbidden: Insufficient permissions"/> </handler> <handler statusCode="404"> <log level="ERROR" message="Connector not found"/> </handler> <handler statusCode="500"> <log level="ERROR" message="Server error: Retry later"/> </handler> </errorHandling> </httpClient> ``

Microflow: CheckOperationPolicy

```xml <microflow name="CheckOperationPolicy"> <parameters> <parameter name="Connector" type="String"/> <parameter name="Operation" type="String"/> <parameter name="Parameters" type="String"/> <!-- JSON string --> </parameters>

<!-- Build request JSON --> <createVariableSetter variable="RequestBody"> { "connector": $Connector, "operation": $Operation, "params": $Parameters } </createVariableSetter>

<!-- Call ARX API --> <callRest endpoint="POST /v1/lowcode/policy-check"> <request>$RequestBody</request> </callRest>

<!-- Parse response --> <parseJson output="PolicyResponse" input="$ResponseBody"/>

<!-- Handle errors --> <ifElse condition="$ResponseStatusCode >= 400"> <true> <log level="ERROR" message="Policy check failed: {0}" args="[$ResponseBody]"/> <return>null</return> </true> <false> <return>$PolicyResponse</return> </false> </ifElse> </microflow> ```

Microflow: ExecuteSecurityOperation

```xml <microflow name="ExecuteSecurityOperation"> <parameters> <parameter name="Connector" type="String"/> <parameter name="Operation" type="String"/> <parameter name="Parameters" type="String"/> <!-- JSON --> <parameter name="RequireApproval" type="Boolean" default="false"/> </parameters>

<!-- Validate inputs --> <ifElse condition="empty($Connector) or empty($Operation)"> <true> <throwException message="Connector and Operation are required"/> </true> </ifElse>

<!-- Build request --> <createVariableSetter variable="ExecuteRequest"> { "connector": $Connector, "operation": $Operation, "params": parseJson($Parameters), "require_approval": $RequireApproval, "user_context": { "app_name": $CurrentUser.App, "user_id": $CurrentUser.UserID } } </createVariableSetter>

<!-- Call API --> <callRest endpoint="POST /v1/lowcode/execute"> <request>$ExecuteRequest</request> </callRest>

<!-- Parse response --> <parseJson output="ExecutionResult" input="$ResponseBody"/>

<!-- Check verdict --> <ifElse condition="$ExecutionResult.success"> <true> <log level="INFO" message="Operation {0} succeeded. Risk: {1}, Verdict: {2}" args="[$Operation, $ExecutionResult.risk_score, $ExecutionResult.verdict]"/> </true> <false> <log level="ERROR" message="Operation failed: {0}" args="[$ExecutionResult.error]"/> <throwException message="$ExecutionResult.error"/> </false> </ifElse>

<return>$ExecutionResult</return> </microflow> ```

Security Considerations

1. API Key Management

  • Store API key in Mendix Vault (encrypted)
  • Never log API keys
  • Rotate keys every 90 days
  • Use service account keys, not personal

2. Input Validation

  • Validate connector names against allowed list
  • Validate operation names (must be in OPERATION_MAP)
  • Sanitize JSON parameters
  • Enforce parameter type checking

3. Audit Trail

  • Log all policy verdicts
  • Log all executed operations
  • Capture user context (who, when, what)
  • Export audit logs to external SIEM

4. Rate Limiting

  • Implement local rate limiting (X requests/minute)
  • Respect ARX rate limit headers
  • Queue requests if limit approaching
  • Alert on rate limit exceeded

Testing

Unit Tests

Test each microflow in isolation:

``xml <test name="TestPolicyCheckerWithPermitVerdict"> <setup> <!-- Create test connector config --> </setup> <execute> <call microflow="CheckOperationPolicy"> <arg name="Connector">okta</arg> <arg name="Operation">users:read</arg> <arg name="Parameters">{"limit": 10}</arg> </call> </execute> <assert condition="$PolicyResponse.verdict = 'PERMIT'"/> <assert condition="$PolicyResponse.risk_score < 25"/> </test> ``

Integration Tests

Test end-to-end workflows:

``xml <test name="TestUserDeactivationWithApproval"> <setup> <!-- Configure high-risk policy for users:deactivate --> </setup> <execute> <!-- Call CheckOperationPolicy → should return ESCALATE --> <!-- Call ExecuteSecurityOperation → should queue for approval --> <!-- Verify audit log entry created --> </execute> <assert condition="$ExecutionResult.requires_approval = true"/> </test> ``

Version History

| Version | Changes | |---------|---------| | 1.0.0 | Initial release: Policy checker, operation executor, audit widget |

Roadmap

  • [ ] v1.1: Batch operation execution
  • [ ] v1.2: Approval workflow UI components
  • [ ] v1.3: Mendix native widgets (not web-based)
  • [ ] v1.4: Offline mode with sync-on-reconnect
  • [ ] v2.0: GraphQL API support