Skip to main content
Tools

Validation Server

⏱ 3 min readEdit on GitHub ↗

The @finos/calm-server package provides a standalone HTTP server for CALM architecture validation. It exposes REST API endpoints that allow you to validate CALM architectures remotely. This makes it ideal to include in application containers to provide CALM validation capability, without requiring subprocess invocations.

The separation from the @finos/calm-cli package may also allow organizations to control the server availability.

Overview​

While the CLI provides command-line validation, the validation server enables remote validation via HTTP requests.

All CALM schemas (release and draft versions) are bundled with the server, so no additional schema files are required.

Installation​

Install the validation server globally:

npm install -g @finos/calm-server

Or use it within a project:

npm install --save-dev @finos/calm-server

Starting the Server​

Basic Usage​

Start the server with default settings (listens on localhost:3000):

calm-server

The server will start and display:

CALM Server is running on http://127.0.0.1:3000

With Custom Port​

calm-server --port 8080

With Verbose Logging​

calm-server --verbose

With Custom Schema Directory​

By default, the server uses bundled CALM schemas. To use custom schemas:

calm-server --schema-directory /path/to/calm/schemas

Command-Line Options​

OptionDescriptionDefault
-V, --versionOutput the version number-
--port <port>Port to run the server on3000
--host <host>Host to bind the server to127.0.0.1
-s, --schema-directory <path>Path to custom CALM schema filesBundled schemas
-v, --verboseEnable verbose loggingfalse
-c, --calm-hub-url <url>URL to CALMHub instance for remote schema resolution-
--rate-limit-window <ms>Rate limit window in milliseconds900000 (15 min)
--rate-limit-max <requests>Max requests per IP within rate limit window100
-h, --helpDisplay help information-

API Endpoints​

Health Check​

Check if the server is running and responsive.

Endpoint: GET /health

Example:

curl http://localhost:3000/health

Response:

{
"status": "OK"
}

Validate Architecture​

Validate a CALM architecture document against the appropriate schema.

Endpoint: POST /calm/validate

Headers:

  • Content-Type: application/json

Request Body:

{
"architecture": "{\"$schema\":\"https://calm.finos.org/release/1.2/meta/calm.json\",\"nodes\":[]}"
}

The architecture field should contain a stringified JSON representation of your CALM architecture.

Example Request:

curl -X POST http://localhost:3000/calm/validate \
-H "Content-Type: application/json" \
-d '{
"architecture": "{\"$schema\":\"https://calm.finos.org/release/1.2/meta/calm.json\",\"nodes\":[],\"relationships\":[]}"
}'

Response (Valid Architecture):

{
"jsonSchemaValidationOutputs": [],
"spectralSchemaValidationOutputs": [],
"hasErrors": false,
"hasWarnings": false
}

Response (Invalid Architecture):

{
"jsonSchemaValidationOutputs": [
{
"valid": false,
"errors": [
{
"instancePath": "/nodes/0",
"schemaPath": "#/properties/nodes/items/required",
"keyword": "required",
"params": { "missingProperty": "unique-id" },
"message": "must have required property 'unique-id'"
}
]
}
],
"spectralSchemaValidationOutputs": [],
"hasErrors": true,
"hasWarnings": false
}

Security Considerations​

warning

The validation server has no built-in authentication or authorization. It is designed for use in trusted environments.

Default Security Settings​

  • Localhost Binding: By default, the server binds to 127.0.0.1, making it accessible only from the local machine
  • Rate Limiting: Enabled by default (100 requests per 15 minutes per IP)
  • Security Warning: When binding to non-localhost addresses, a warning is logged

Network Exposure​

When exposing the server to a network (using --host 0.0.0.0 or a specific IP):

calm-server --host 0.0.0.0 --port 3000

The server will log:

⚠️ WARNING: Server is configured to listen on 0.0.0.0
⚠️ This server has NO authentication or authorization controls.
⚠️ Only bind to non-localhost addresses in trusted network environments.

Best Practices:

  • Use a reverse proxy (nginx, Apache) with authentication
  • Deploy behind a VPN or firewall
  • Use network-level access controls
  • Monitor usage and logs

Use Cases​

Web Application Integration​

Use the validation server as a backend for web-based CALM editors:

async function validateArchitecture(architectureJson) {
const response = await fetch('http://localhost:3000/calm/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
architecture: JSON.stringify(architectureJson)
})
});

const result = await response.json();

if (result.hasErrors) {
console.error('Validation errors:', result.jsonSchemaValidationOutputs);
}

return result;
}

Docker Deployment​

Create a Dockerfile for containerized deployment:

FROM node:22-alpine

RUN npm install -g @finos/calm-server

EXPOSE 3000

CMD ["calm-server", "--host", "0.0.0.0", "--port", "3000"]

Build and run:

docker build -t calm-server .
docker run -p 3000:3000 calm-server

Rate Limiting​

The server includes built-in rate limiting to prevent abuse:

  • Default Window: 15 minutes (900,000 ms)
  • Default Max Requests: 100 per IP address

Customizing Rate Limits​

Adjust rate limits based on your use case:

# Higher limits for internal team usage
calm-server \
--rate-limit-window 3600000 \
--rate-limit-max 1000

# Stricter limits for public-facing instances
calm-server \
--rate-limit-window 600000 \
--rate-limit-max 50

Rate Limit Response​

When rate limits are exceeded, the server returns:

HTTP 429 Too Many Requests

Too many requests, please try again later.

Troubleshooting​

Server Won't Start​

Problem: Port already in use

Error: listen EADDRINUSE: address already in use 127.0.0.1:3000

Solution: Use a different port or stop the process using port 3000:

# Use different port
calm-server --port 8080

# Or find and stop the process
lsof -i :3000
kill -9 <PID>

Validation Fails with Valid Architecture​

Problem: Architecture validates with CLI but fails with server

Solution: Ensure the architecture is properly stringified in the request body:

// Correct: Stringified JSON
{
"architecture": "{\"$schema\":\"...\",\"nodes\":[]}"
}

// Incorrect: Plain JSON object
{
"architecture": {"$schema": "...", "nodes": []}
}

Connection Refused​

Problem: Cannot connect to server

curl: (7) Failed to connect to localhost port 3000: Connection refused

Solution:

  1. Verify the server is running
  2. Check the port number
  3. Ensure firewall allows connections

See Also​

  • CLI - General CLI usage, installation, and commands