or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

copilot-chatmode-command.mddocify-command.mdgenerate-command.mdindex.mdserver-command.mdtemplate-command.mdvalidate-command.md

server-command.mddocs/

0

# Server Command

1

2

> **NOTE**: This is a CLI-only command. @finos/calm-cli does not export functions for programmatic use.

3

4

The `server` command starts an HTTP server providing REST API access to CALM validation operations. This experimental feature enables programmatic validation through HTTP requests, useful for integrating CALM validation into web applications, microservices, or CI/CD pipelines.

5

6

## Capabilities

7

8

### Server Command

9

10

Start an HTTP server to provide REST API access to validation operations.

11

12

```typescript { .api }

13

/**

14

* Start a HTTP server to proxy CLI commands (experimental)

15

* @command calm server [options]

16

*/

17

interface ServerCommandOptions {

18

/** Server port

19

* CLI flags: --port <port>

20

* Default: "3000"

21

*/

22

port?: string;

23

24

/** Path to directory containing meta schemas

25

* CLI flags: -s, --schema-directory <path>

26

* Required: yes

27

*/

28

schemaDirectory: string;

29

30

/** Enable verbose logging

31

* CLI flags: -v, --verbose

32

* Default: false

33

*/

34

verbose?: boolean;

35

}

36

```

37

38

**Usage Examples:**

39

40

```bash

41

# Start server on default port 3000

42

calm server -s ./calm/schemas

43

44

# Start server on custom port

45

calm server --port 8080 -s ./calm/schemas

46

47

# Start with verbose logging

48

calm server --port 3000 -s ./calm/schemas -v

49

```

50

51

## API Endpoints

52

53

### Health Check

54

55

Check server health status.

56

57

```typescript { .api }

58

/**

59

* GET /health

60

* Health check endpoint

61

* @returns StatusResponse with status "OK"

62

*/

63

interface HealthCheckEndpoint {

64

method: 'GET';

65

path: '/health';

66

response: StatusResponse;

67

}

68

69

interface StatusResponse {

70

status: string; // "OK"

71

}

72

```

73

74

**Example Request:**

75

76

```bash

77

curl http://localhost:3000/health

78

```

79

80

**Example Response:**

81

82

```json

83

{

84

"status": "OK"

85

}

86

```

87

88

### Validate Architecture

89

90

Validate a CALM architecture against its embedded schema.

91

92

```typescript { .api }

93

/**

94

* POST /calm/validate

95

* Validate CALM architecture

96

* @rateLimit 100 requests per 15 minutes per IP

97

* @returns ValidationOutcome on success or ErrorResponse on failure

98

*/

99

interface ValidateEndpoint {

100

method: 'POST';

101

path: '/calm/validate';

102

headers: {

103

'Content-Type': 'application/json';

104

};

105

body: ValidationRequest;

106

response: ValidationOutcome | ErrorResponse;

107

statusCodes: {

108

201: 'Validation completed successfully';

109

400: 'Invalid request (missing $schema, invalid JSON)';

110

429: 'Rate limit exceeded';

111

500: 'Server error (schema loading failed, validation error)';

112

};

113

}

114

115

interface ValidationRequest {

116

/** JSON string containing CALM architecture */

117

architecture: string;

118

}

119

120

interface ErrorResponse {

121

error: string;

122

}

123

```

124

125

**Example Request:**

126

127

```bash

128

curl -X POST http://localhost:3000/calm/validate \

129

-H "Content-Type: application/json" \

130

-d '{

131

"architecture": "{\"$schema\":\"https://calm.finos.org/schemas/calm-v1.json\",\"nodes\":[]}"

132

}'

133

```

134

135

**Example Success Response (201):**

136

137

```json

138

{

139

"jsonSchemaValidationOutputs": [],

140

"spectralSchemaValidationOutputs": [],

141

"hasErrors": false,

142

"hasWarnings": false

143

}

144

```

145

146

**Example Error Response (400):**

147

148

```json

149

{

150

"error": "The \"$schema\" field is missing from the request body"

151

}

152

```

153

154

**Example Error Response (429):**

155

156

```json

157

{

158

"error": "Too many requests, please try again later."

159

}

160

```

161

162

## Configuration

163

164

### CALMHub Integration

165

166

The server command uses CALMHub URL from the user configuration file for remote pattern and schema loading:

167

168

**Via User Configuration File (`~/.calm.json`):**

169

170

```json

171

{

172

"calmHubUrl": "https://calmhub.example.com"

173

}

174

```

175

176

**Important Distinction from Generate Command:**

177

178

Unlike the `generate` command which accepts both a `-c, --calm-hub-url` command-line option and configuration file setting, the **server command does NOT accept `--calm-hub-url` as a command-line option**. The server will **only** use the CALMHub URL from the `~/.calm.json` configuration file if present.

179

180

**Rationale:** The server needs a consistent configuration that doesn't change per-request. Since the server runs continuously and handles multiple validation requests, having a stable, file-based configuration is more appropriate than per-invocation command-line options.

181

182

**To configure CALMHub for the server:**

183

1. Create or edit `~/.calm.json` in your home directory

184

2. Add the `calmHubUrl` property with your CALMHub instance URL

185

3. Restart the server to pick up the new configuration

186

187

## Rate Limiting

188

189

The validation endpoint includes rate limiting to prevent abuse:

190

191

- **Limit:** 100 requests per 15 minutes per IP address

192

- **Response:** 429 Too Many Requests when limit exceeded

193

- **Headers:** Rate limit information included in response headers

194

195

## Server Architecture

196

197

### Express Application Structure

198

199

```typescript { .api }

200

/**

201

* Express router configuration for all server routes

202

*/

203

class CLIServerRoutes {

204

router: Router;

205

206

/**

207

* @param schemaDirectory - SchemaDirectory instance for validation

208

* @param debug - Enable debug logging (default: false)

209

*/

210

constructor(schemaDirectory: SchemaDirectory, debug?: boolean);

211

}

212

213

/**

214

* Express router for validation API endpoint

215

* Includes rate limiting and error handling

216

*/

217

class ValidationRouter {

218

/**

219

* @param router - Express Router instance

220

* @param schemaDirectory - SchemaDirectory instance for validation

221

* @param debug - Enable debug logging (default: false)

222

*/

223

constructor(

224

router: Router,

225

schemaDirectory: SchemaDirectory,

226

debug?: boolean

227

);

228

}

229

230

/**

231

* Express router for health check endpoint

232

*/

233

class HealthRouter {

234

/**

235

* @param router - Express Router instance

236

*/

237

constructor(router: Router);

238

}

239

```

240

241

## Request/Response Flow

242

243

### Validation Request Flow

244

245

1. **Request Received:** POST request to `/calm/validate`

246

2. **Rate Limit Check:** Verify IP hasn't exceeded rate limit

247

3. **JSON Parsing:** Parse architecture from request body

248

4. **Schema Extraction:** Extract `$schema` field from architecture

249

5. **Schema Loading:** Load and validate schema from SchemaDirectory

250

6. **Validation:** Perform JSON schema and Spectral validation

251

7. **Response:** Return ValidationOutcome or ErrorResponse

252

253

### Error Scenarios

254

255

**Missing $schema Field:**

256

```json

257

{

258

"error": "The \"$schema\" field is missing from the request body"

259

}

260

```

261

262

**Invalid JSON:**

263

```json

264

{

265

"error": "Invalid JSON format for architecture"

266

}

267

```

268

269

**Schema Not Available:**

270

```json

271

{

272

"error": "The \"$schema\" field referenced is not available to the server"

273

}

274

```

275

276

**Validation Failed:**

277

```json

278

{

279

"error": "Validation error message"

280

}

281

```

282

283

## Integration Examples

284

285

### Node.js Client

286

287

```typescript

288

import axios from 'axios';

289

290

async function validateArchitecture(architecture: object) {

291

try {

292

const response = await axios.post('http://localhost:3000/calm/validate', {

293

architecture: JSON.stringify(architecture)

294

});

295

296

console.log('Validation result:', response.data);

297

return response.data;

298

} catch (error) {

299

if (error.response) {

300

console.error('Validation failed:', error.response.data.error);

301

} else {

302

console.error('Request failed:', error.message);

303

}

304

throw error;

305

}

306

}

307

308

// Usage

309

const myArchitecture = {

310

"$schema": "https://calm.finos.org/schemas/calm-v1.json",

311

"nodes": [

312

{

313

"unique-id": "api-gateway",

314

"node-type": "system",

315

"name": "API Gateway"

316

}

317

]

318

};

319

320

await validateArchitecture(myArchitecture);

321

```

322

323

### Python Client

324

325

```python

326

import requests

327

import json

328

329

def validate_architecture(architecture):

330

url = 'http://localhost:3000/calm/validate'

331

headers = {'Content-Type': 'application/json'}

332

payload = {

333

'architecture': json.dumps(architecture)

334

}

335

336

response = requests.post(url, json=payload, headers=headers)

337

338

if response.status_code == 201:

339

return response.json()

340

else:

341

raise Exception(f"Validation failed: {response.json()['error']}")

342

343

# Usage

344

my_architecture = {

345

"$schema": "https://calm.finos.org/schemas/calm-v1.json",

346

"nodes": []

347

}

348

349

result = validate_architecture(my_architecture)

350

print("Validation result:", result)

351

```

352

353

### cURL Examples

354

355

```bash

356

# Valid architecture

357

curl -X POST http://localhost:3000/calm/validate \

358

-H "Content-Type: application/json" \

359

-d @- << 'EOF'

360

{

361

"architecture": "{\"$schema\":\"https://calm.finos.org/schemas/calm-v1.json\",\"nodes\":[]}"

362

}

363

EOF

364

365

# Architecture with validation errors

366

curl -X POST http://localhost:3000/calm/validate \

367

-H "Content-Type: application/json" \

368

-d '{"architecture": "{\"nodes\":[]}"}'

369

370

# Health check

371

curl http://localhost:3000/health

372

```

373

374

## Configuration

375

376

### Schema Directory

377

378

The server requires a schema directory containing CALM meta schemas:

379

380

```bash

381

calm server -s ./calm/release

382

```

383

384

The schema directory should contain:

385

- Meta schemas for CALM architecture validation

386

- Pattern schemas

387

- Any custom schemas

388

389

### Port Configuration

390

391

Default port is 3000, but can be customized:

392

393

```bash

394

calm server --port 8080 -s ./schemas

395

```

396

397

**Important:** Ensure the port is not already in use by another application.

398

399

### Verbose Logging

400

401

Enable verbose logging for debugging:

402

403

```bash

404

calm server --port 3000 -s ./schemas -v

405

```

406

407

Verbose mode logs:

408

- Schema loading operations

409

- Validation requests and results

410

- Error details

411

412

## Deployment Considerations

413

414

### Production Deployment

415

416

For production use, consider:

417

418

1. **Reverse Proxy:** Use nginx or Apache as reverse proxy

419

2. **HTTPS:** Enable SSL/TLS for secure communication

420

3. **Authentication:** Add authentication middleware

421

4. **Rate Limiting:** Adjust rate limits based on usage patterns

422

5. **Monitoring:** Add application monitoring and health checks

423

6. **Process Management:** Use PM2 or systemd for process management

424

425

### Docker Deployment

426

427

Example Dockerfile:

428

429

```dockerfile

430

FROM node:18-alpine

431

432

WORKDIR /app

433

434

# Install CALM CLI

435

RUN npm install -g @finos/calm-cli

436

437

# Copy schemas

438

COPY ./schemas /app/schemas

439

440

# Expose port

441

EXPOSE 3000

442

443

# Start server

444

CMD ["calm", "server", "--port", "3000", "-s", "/app/schemas"]

445

```

446

447

### Kubernetes Deployment

448

449

Example Kubernetes manifest:

450

451

```yaml

452

apiVersion: apps/v1

453

kind: Deployment

454

metadata:

455

name: calm-server

456

spec:

457

replicas: 3

458

selector:

459

matchLabels:

460

app: calm-server

461

template:

462

metadata:

463

labels:

464

app: calm-server

465

spec:

466

containers:

467

- name: calm-server

468

image: calm-server:latest

469

ports:

470

- containerPort: 3000

471

env:

472

- name: PORT

473

value: "3000"

474

---

475

apiVersion: v1

476

kind: Service

477

metadata:

478

name: calm-server

479

spec:

480

selector:

481

app: calm-server

482

ports:

483

- port: 80

484

targetPort: 3000

485

type: LoadBalancer

486

```

487

488

## Limitations

489

490

**Experimental Feature:**

491

The server command is marked as experimental and may have limitations:

492

493

1. **Pattern Validation Not Supported:** Server only validates against embedded `$schema`, not separate pattern files

494

2. **No Authentication:** No built-in authentication or authorization

495

3. **Limited Output Formats:** Only JSON output format supported

496

4. **Basic Rate Limiting:** Simple IP-based rate limiting without persistence

497

498

**Use Cases:**

499

- Development and testing environments

500

- Internal microservice integration

501

- CI/CD pipeline integration

502

- Web application backends

503

504

**Not Recommended For:**

505

- Public internet exposure without additional security

506

- High-traffic production environments without load balancing

507

- Scenarios requiring pattern-based validation (use CLI directly)

508

509

## Error Handling

510

511

### Server Startup Errors

512

513

**Port Already in Use:**

514

```

515

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

516

```

517

**Solution:** Use a different port or stop the conflicting process.

518

519

**Schema Directory Not Found:**

520

```

521

Error: ENOENT: no such file or directory

522

```

523

**Solution:** Verify schema directory path is correct.

524

525

**Permission Denied:**

526

```

527

Error: listen EACCES: permission denied

528

```

529

**Solution:** Use a port number > 1024 or run with appropriate permissions.

530

531

### Runtime Errors

532

533

All runtime errors are caught and returned as ErrorResponse with appropriate HTTP status codes. The server remains running and available for subsequent requests.

534

535

## Monitoring

536

537

### Health Check Monitoring

538

539

Use the `/health` endpoint for uptime monitoring:

540

541

```bash

542

# Simple health check

543

curl -f http://localhost:3000/health || echo "Server down"

544

545

# With monitoring tool

546

watch -n 30 'curl -s http://localhost:3000/health | jq .status'

547

```

548

549

### Logging

550

551

The server logs important events:

552

- Server startup and port binding

553

- Schema loading success/failure

554

- Validation requests (in verbose mode)

555

- Errors and warnings

556

557

Access logs through the application's stdout/stderr.

558