Skip to main content

Validation Server

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