# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**Software Deployment Service (SDS)** is a Spring Boot microservice that orchestrates software deployments across NetFoundry infrastructure. It serves as a central control plane for managing network controllers, edge routers, and other infrastructure components via Salt state management and Ansible automation.

The service exposes a REST API on port 9302 to manage deployments, certificates, hosts, backups, and cron jobs across multiple environments (development, sandbox, staging, production).

## Tech Stack

- **Language**: Java 21
- **Framework**: Spring Boot 3.4.5 with Spring Cloud (2024.0.1)
- **Build Tool**: Maven (with Maven Wrapper)
- **Build System**: Maven-based, includes Docker image generation
- **Configuration Management**: Salt (via HTTP), Ansible (for deployments)
- **Cloud Infrastructure**: AWS (ECS, RabbitMQ, Secrets Manager, S3, Route53, SSM, SecretsManager)
- **Security**: OpenZiti network (for secure service-to-service communication), Auth0
- **Infrastructure as Code**: Terraform (AWS provisioning)
- **Metrics**: Micrometer with Elasticsearch reporting
- **Testing**: JUnit 5, Mockito, JaCoCo (code coverage), REST Assured (API testing)
- **Code Generation**: Lombok, MapStruct
- **Container**: Docker (Chainguard-based)

## Build, Test, and Lint Commands

### Build
```bash
# Standard Maven build (clean install with tests)
./install.sh

# Maven clean install (equivalent)
./mvnw clean install

# Build Spring Boot jar directly
./mvnw spring-boot:build-info spring-boot:repackage

# Build and package as Docker image (CI/CD pipelines handle this)
docker build -t sds:latest .
```

### Run Locally
```bash
# Run the Spring Boot application locally with development profile
./run.sh

# With custom JVM arguments
./run.sh -Xmx2048m

# The script sets SPRING_PROFILES_ACTIVE=development and configures AWS credentials
```

### Tests
```bash
# Run all tests
./mvnw test

# Run a specific test class
./mvnw test -Dtest=NetworkDeploymentControllerTest

# Run a specific test method
./mvnw test -Dtest=NetworkDeploymentControllerTest#testMethodName

# Run tests with code coverage report (JaCoCo)
./mvnw clean verify
# Coverage reports: target/jacoco-ut/index.html

# Tests use @SpringBootTest with WireMock servers for Salt and Ansible mocking
```

### Linting and Code Quality
```bash
# Pre-commit hooks (Ansible, Salt, YAML validation)
pre-commit run --all-files

# Specific linters:
# - Ansible: ansible-lint -c ./ansible/.ansible-lint.yaml
# - Salt: salt-lint -c ./saltstate/.salt-lint.yaml  
# - YAML: yamllint

# SonarQube analysis (configured for SonarCloud)
./mvnw sonar:sonar -Dsonar.login=<SONAR_TOKEN>
# Or via sonar.sh script for CI/CD integration

# Dependency vulnerability scanning (OWASP)
./mvnw -Pdependency_check dependency-check:check
# Report: target/dependency-check-report.html
```

## Architecture Overview

### High-Level Components

The application follows a layered microservice architecture:

```
REST Controllers
    ↓
Service Layer (Business Logic)
    ↓
Salt/Ansible Orchestration Layer
    ↓
AWS Cloud Services & Salt Master
```

### Core Modules

1. **Controllers** (`src/main/java/io/netfoundry/sds/controller/`)
   - `HostController`: Manage hosts and their configuration (ping, status, list)
   - `NetworkDeploymentController`: Manage network deployments
   - `NetworkControllerDeploymentController`: Deploy/manage network controllers (primary Ziti component)
   - `EdgeRouterDeploymentController`: Deploy/manage edge routers
   - `IpsecTunnelerDeploymentController`: IPsec tunnel configuration
   - `CertificateController`: Certificate management
   - `BackupController`: Host/controller backups
   - `CronDeploymentController`: Scheduled deployment tasks

2. **Service Layer** (`src/main/java/io/netfoundry/sds/service/`)
   - **Core Services** (`service/core/`): `CoreInformationService` - fetches network/controller/host metadata from MOP database via common-util-framework
   - **Data Services** (`service/data/`): HTTP JSON API for Salt pillar data (host configuration)
   - **Certificate Services** (`service/certificates/`): SSL/TLS certificate handling
   - **DNS Services** (`service/dns/`): Route53 DNS management
   - **Version Services** (`service/version/`): Version tracking and management

3. **Salt Integration** (`src/main/java/io/netfoundry/sds/salt/`)
   - `SaltService`: Primary API for applying Salt states and running Salt functions/runners
   - `SaltClient`: HTTP client for communicating with Salt Master (supports both RestClient and legacy WebClient via `sds.salt.http-client` property)
   - `SaltConfiguration`: Configures Salt client with Ziti context from AWS Secrets Manager
   - Domain objects: `SaltJob`, `SaltState`, `SaltFunction`, `SaltRunner`, `SaltOrchestrationResult`
   - Feature flag: `sds.salt.http-client=RestClient` (default) or `WebClient` for legacy client

4. **Ansible Integration** (`src/main/java/io/netfoundry/sds/ansible/`)
   - `NetworkControllerAnsibleWrapper`: Wrapper for Ansible playbook execution
   - Ansible playbooks in `/ansible/` directory handle complex deployment workflows
   - Collections: OpenZiti community collection for paramiko-based Ziti network communication

5. **Deployment Management** (`src/main/java/io/netfoundry/sds/deployments/`)
   - `JobPollingService`: Polls Salt job status asynchronously
   - Deployment tracking and status updates

6. **Domain Objects** (`src/main/java/io/netfoundry/sds/domain/`)
   - `Host`, `Network`, `NetworkController`: Core infrastructure entities (mirrored from MOP via common-util-framework)
   - Subdomains for `host/`, `network/`, `ipsectunneler/`: Type-specific configurations
   - Host pillar data models: `MinionPillarData`, `EdgeRouterMinionPillarData`, `NetworkControllerMinionPillarData`

7. **Security & Configuration** (`src/main/java/io/netfoundry/sds/config/`)
   - `AuthUtilService`: Auth0-based authorization via common-util-framework
   - `SaltConfiguration`: Salt client bean setup with Ziti context
   - `SecretManager`: AWS Secrets Manager integration for retrieving private keys, passwords, etc.

### Data Flow Example: Deploying a Network Controller

1. Client → POST `/network-controllers/deploy` with configuration
2. `NetworkControllerDeploymentController` validates authorization and parameters
3. Calls `SaltService.add()` to apply network controller Salt state to minions
4. `SaltClient` sends HTTP request to Salt Master (via Ziti network)
5. Salt Master applies state on target hosts and returns job ID
6. `JobPollingService` polls job status via RabbitMQ (Salt-Ingress exchange)
7. Status updates published back to client (WebSocket or polling)

### Key Integration Points

- **Salt Master**: HTTP-based API for state/function execution, accessed via Ziti network (no certificate validation due to `spring.ziti.client.tls-socket-strategy.enabled=false`)
- **AWS Services**:
  - Secrets Manager: Private keys, certificates, Auth0 credentials
  - RabbitMQ (AWS MQ): Event streaming from Salt
  - Route53: DNS record management
  - S3: Artifact storage
  - ECS: Service deployment and scaling
- **Ziti Network**: Encrypted secure service mesh communication (configured via identity in Secrets Manager)
- **MOP Database**: Source of truth for network/host/controller metadata (accessed via common-util-framework)

### Environment Profiles

Configuration is managed via Spring profiles:
- `application.properties`: Common settings (all environments)
- `application-development.properties`: Local development
- `application-sandbox.properties`: Sandbox environment
- `application-staging.properties`: Staging environment
- `application-production.properties`: Production environment

Key configurations in `application.properties`:
- `server.port=9302`
- `sds.salt.port=8001`
- `sds.salt.http-client=RestClient` (feature flag for HTTP client type)
- Spring Actuator endpoints (health, metrics, heapdump)
- Elasticsearch metrics export
- RabbitMQ connection for Salt events

## Project Structure

```
.
├── src/main/java/io/netfoundry/sds/         # Java source code
│   ├── controller/                            # REST endpoints
│   ├── service/                               # Business logic (core, data, certificates, dns, version)
│   ├── salt/                                  # Salt orchestration
│   ├── ansible/                               # Ansible wrappers
│   ├── deployments/                           # Deployment tracking
│   ├── domain/                                # Domain models (host, network, ipsectunneler)
│   ├── config/                                # Spring configuration beans
│   └── util/                                  # Utility classes
├── src/main/resources/
│   ├── application.properties                 # Common configuration
│   ├── application-*.properties               # Environment-specific configs
│   └── static/docs/                           # API documentation
├── src/test/java/                             # Unit and integration tests
├── ansible/                                   # Ansible playbooks and roles
│   ├── roles/                                 # Ansible roles
│   ├── requirements.yaml                      # Ansible collections
│   └── .ansible-lint.yaml                     # Ansible linting config
├── saltstate/                                 # Salt state files
├── terraform/                                 # AWS infrastructure as code
├── jenkinsfiles/                              # Jenkins pipeline definitions
├── taurus/                                    # Performance testing (Taurus/BlazeMeter)
├── owasp/                                     # OWASP dependency check config
├── Dockerfile                                 # Container image definition
├── pom.xml                                    # Maven configuration
├── mvnw / mvnw.cmd                            # Maven wrapper
└── run.sh / install.sh / startup.sh           # Convenience scripts
```

## Testing Strategy

- **Unit Tests**: Standard JUnit 5 tests with Mockito, located alongside controllers/services
- **Integration Tests**: Use `@SpringBootTest` with WireMock to mock Salt and Ansible responses
- **Base Test Class**: `BaseServiceTest` provides common test setup (configuration, mocking)
- **Test Data**: Mock servers (OkHttp MockWebServer) simulate Salt and Ansible responses
- **Coverage Tracking**: JaCoCo generates code coverage reports; SonarCloud tracks trends

Base test configuration in `src/test/java/io/netfoundry/sds/config/` includes:
- `SaltTestConfiguration`: Mocks Salt HTTP client
- `ServerTestConfiguration`: Test server setup
- `AuthorizationTestConfiguration`: Auth mocking

## CI/CD Pipeline

Jenkins pipelines (in `jenkinsfiles/`) orchestrate:
1. **Build**: Compile, test, build Docker image
2. **SonarQube Analysis**: Code quality scanning
3. **OWASP Dependency Check**: Vulnerability scanning
4. **Docker Registry Push**: Push image to registry
5. **ECS Deployment**: Update ECS service with new image

Key stages in `serverless-develop-pipeline.jenkinsfile`:
- Docker Build/Push
- Smoke tests
- SonarQube analysis
- Deployment to sandbox, staging, production

## Important Notes

### Reactive/Non-Blocking Behavior
- Spring WebFlux is included for reactive processing (`spring-boot-starter-webflux`)
- `Hooks.enableAutomaticContextPropagation()` in main class enables context propagation for reactive chains
- The Salt HTTP client supports both reactive (WebClient) and traditional (RestClient) modes

### Ziti Network Integration
- Configured to use OpenZiti for secure service mesh communication
- Identity is fetched from AWS Secrets Manager
- SSL certificate name validation is disabled for Salt connections
- Requires OpenZiti SDK (v0.33.1) and Ansible collection

### Salt State Management
- States are applied via HTTP to a Salt Master
- Actions: ADD (deploy) and REMOVE (teardown) are explicit in state definitions
- Results are streamed via RabbitMQ (Salt-Ingress exchange)
- Job polling is asynchronous via `JobPollingService`

### Deployment Exclusions (SonarQube Coverage)
The following are excluded from coverage reports:
- Configuration classes (`**/config/*`)
- Common exception handler
- Service implementations for higher-level operations
- Salt domain models
- Ansible module code

### Build Properties
- Maven builds inject version and timestamp into application: `@project.version@`, `@maven.build.timestamp@`
- Git commit information is included via git-commit-id-plugin

## Docker Deployment

The Dockerfile uses a Chainguard minimal base image and includes:
- OpenJDK 21
- Python 3 with Ansible 10.3.0
- OpenZiti Python SDK
- AWS CLI
- Required Ansible collections from `ansible/requirements.yaml`

The image exposes port 9302 and runs under a non-root user (`noone`).

## Useful Debugging

- **Application logs**: Set `logging.level.io.netfoundry=DEBUG` (already enabled)
- **HTTP audit logs**: Uncomment logbook dependency in pom.xml and set `logging.level.org.zalando.logbook.Logbook=TRACE`
- **Health check**: GET `/actuator/health`
- **Metrics**: GET `/actuator/metrics`
- **Thread dump**: GET `/actuator/threaddump`
- **Heap dump**: GET `/actuator/heapdump`

