← Browse

@cjmalloy/jasper

Jasper Knowledge Management Server

instructionscopilot

Install

agr install @cjmalloy/jasper --target copilot

Writes 1 file into .github/copilot-instructions.md, pinned to git-789b837f.

  • .github/copilot-instructions.md

Document

Jasper Knowledge Management Server

ALWAYS follow these instructions and only fall back to additional search and context gathering if the information in these instructions is incomplete or found to be in error.

Working Effectively

Bootstrap, build, and test the repository:

⚠️ CRITICAL: Java Version Requirement

This project uses Spring Boot 4.1.0 and targets Java 25. Use Java 25 for all normal builds; Java 21 is the minimum supported fallback and requires overriding java.version.

Java 25 is now available in the build environment!

Recommended Approach - Use Java 25 Directly:

  1. Set JAVA_HOME to Java 25:

    export JAVA_HOME=/usr/lib/jvm/temurin-25-jdk-amd64
    export PATH=$JAVA_HOME/bin:$PATH
    
  2. Build and test:

    ./mvnw clean compile  # or ./mvnw clean package
    

Alternative - Docker Build:

  • Docker Build: docker build -t jasper .
    • ⚠️ Known Issue: Docker builds may fail with certificate errors (PKIX path building failed) in some environments due to the Java truststore in the Docker base image. This does not affect GitHub Actions CI.
    • Workaround: Use local build with Java 25 instead

Quick Decision Guide

Your SituationBuild ApproachSteps
Most common (Java 25 available)Use Java 25 directly (RECOMMENDED)1. export JAVA_HOME=/usr/lib/jvm/temurin-25-jdk-amd642. export PATH=$JAVA_HOME/bin:$PATH3. ./mvnw clean package
Docker availableUse Docker (may have PKIX cert issues locally)docker build -t jasper .
Java 21 available (fallback)Use Java 21 with version overrideexport JAVA_HOME=/usr/lib/jvm/temurin-21-jdk-amd64 then build with -Djava.version=21

Local Development with Java 25 (RECOMMENDED):

  • Set JAVA_HOME: export JAVA_HOME=/usr/lib/jvm/temurin-25-jdk-amd64
  • Add to PATH: export PATH=$JAVA_HOME/bin:$PATH
  • Install Bun for JavaScript tests: curl -fsSL https://bun.sh/install | bash && export PATH="$HOME/.bun/bin:$PATH"
  • Clean build: ./mvnw clean compile -- takes 11 seconds. NEVER CANCEL. Set timeout to 30+ seconds.
  • Full build with tests: ./mvnw clean package -- takes 85 seconds. NEVER CANCEL. Set timeout to 180+ seconds.
  • Skip tests build: ./mvnw clean package -DskipTests -- takes 15 seconds. NEVER CANCEL. Set timeout to 30+ seconds.

Docker-Based Build (Alternative):

  • Build with Docker: docker build -t jasper . -- takes ~2 minutes. NEVER CANCEL. Set timeout to 600+ seconds.
  • Build builder stage only: docker build --target builder -t jasper-builder . -- takes ~2 minutes. Set timeout to 600+ seconds.
  • Build test stage: docker build --target test -t jasper-test . -- takes ~5 minutes. Set timeout to 600+ seconds.
  • Run tests in Docker: docker run --rm jasper-test -- executes test suite in container
  • Efficient log reading: Pipe output through tail -100 or tee build.log to efficiently read Docker build logs
  • ⚠️ Known Issue: Docker builds may fail with certificate errors (PKIX path building failed) in some local environments. This is caused by the Java truststore in the Docker base image not trusting Maven Central certificates. The --network=host flag does NOT fix this. Use local Java 25 Maven build instead if this occurs.

Fallback - Use Java 21 (if Java 25 not available):

  • Install Java 21: sudo apt-get update && sudo apt-get install -y openjdk-21-jdk
  • Set JAVA_HOME: export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 (or /usr/lib/jvm/temurin-21-jdk-amd64 if using Temurin)
  • Add to PATH: export PATH=$JAVA_HOME/bin:$PATH
  • Important: Since pom.xml targets Java 25, you must add -Djava.version=21 to all Maven commands. Example: ./mvnw clean compile -Djava.version=21

Running the Application

ALWAYS run the bootstrapping steps first.

Docker Compose (Recommended for Development):

  • Full stack: docker compose up -- starts web app, database, and Redis
  • Supporting services only: docker compose up db redis -d -- background database and cache for local development

Local Development:

  • Start supporting services: docker compose up db redis -d
  • Run application: SPRING_PROFILES_ACTIVE=dev SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/jasper SPRING_DATASOURCE_USERNAME=jasper SPRING_DATASOURCE_PASSWORD=jasper ./mvnw spring-boot:run
  • Application starts on port 8081 (takes ~22 seconds to start)
  • Health check: curl http://localhost:8081/management/health

Production Build:

  • Build Docker image: docker build -t jasper . -- takes ~2 minutes. NEVER CANCEL. Set timeout to 600+ seconds.
  • Test Docker build: docker build --target test -t jasper-test . -- takes ~5 minutes. NEVER CANCEL. Set timeout to 600+ seconds.

Testing

Unit and Integration Tests:

  • Local SQLite (Recommended): ./mvnw test -Dspring.profiles.active=test,sqlite,scripts -- runs without PostgreSQL or Docker. NEVER CANCEL. Set timeout to 180+ seconds.
  • Local PostgreSQL/Testcontainers: ./mvnw test -- requires Docker. NEVER CANCEL. Set timeout to 180+ seconds.
  • Docker-based PostgreSQL: docker build --target test -t jasper-test . && docker run --rm -v /var/run/docker.sock:/var/run/docker.sock jasper-test -- takes ~5 minutes. NEVER CANCEL. Set timeout to 600+ seconds.
  • The Docker-based test command mounts the local Docker socket so Testcontainers can start PostgreSQL; only run it with trusted images in a trusted local environment.
  • Note: Some tests require Bun and Python dependencies to pass completely
  • Test failures related to missing /home/runner/.bun/bin/bun are expected without Bun installation

Efficient Log Reading with Docker: When building with Docker, use these techniques to efficiently read logs:

  • Tail output: docker build -t jasper . 2>&1 | tail -100 -- shows last 100 lines
  • Save to file: docker build -t jasper . 2>&1 | tee build.log -- saves full log while showing output
  • Progress mode: docker build --progress=plain -t jasper . -- shows all build output without fancy formatting

Load Testing with Gatling:

  • Navigate to gatling directory: cd gatling
  • PostgreSQL load tests: docker compose --profile lt up --build --exit-code-from gatling -- NEVER CANCEL. Set timeout to 180+ seconds.
  • SQLite load tests: docker compose -f docker-compose.sqlite.yaml --profile lt up --build --exit-code-from gatling -- NEVER CANCEL. Set timeout to 180+ seconds.
  • Docker supported tests: docker compose up -d; ../mvnw gatling:test
  • Run a specific test using the GATLING_TEST environment variable: GATLING_TEST=SmokeTest docker compose --profile lt up --build --exit-code-from gatling
    • Available tests: SmokeTest, Comprehensive, UserJourney, StressTest, Inferno
    • Default test (if not specified): SmokeTest
  • When adding new Gatling simulations: ALWAYS update .github/workflows/gatling.yml to include the new test in the CI pipeline. Add a new step following the pattern of existing tests (e.g., GATLING_TEST=YourNewTest)

GitHub Actions Integration:

  • Build/test workflow: .github/workflows/test.yml builds the Docker image and runs tests against PostgreSQL and SQLite
  • Load test workflow: .github/workflows/gatling.yml runs every Gatling simulation against PostgreSQL and SQLite
  • CodeQL analysis: .github/workflows/codeql.yml runs static security analysis
  • Docker publish: .github/workflows/publish.yml builds and publishes Docker images to GHCR
  • Release: .github/workflows/release.yml creates draft GitHub releases with JAR artifacts
  • GitHub Pages: .github/workflows/pages.yml deploys test reports and documentation
  • Cleanup: .github/workflows/cleanup.yml removes stale PR caches and artifacts
  • Build and test workflows run on push to master and pull requests

Validation

ALWAYS manually validate any new code by running through complete end-to-end scenarios after making changes.

Required Validation Steps:

  1. Start supporting services: docker compose up -d
  2. Test health endpoint: curl http://localhost:8081/management/health (should return {"status":"UP"})
  3. Test API endpoint: curl http://localhost:8081/api/v1/ref/page (should return JSON with empty content array)
  4. Run tests with dependencies: Install Bun and Python, then run both PostgreSQL (./mvnw test) and SQLite (./mvnw test -Dspring.profiles.active=test,sqlite,scripts) suites for complete validation; the SQLite suite is the minimum for changes unrelated to database behavior
  5. Clean up: docker compose down

Key Application Features to Test:

  • RESTful API for knowledge management (Refs, Extensions, Users, Plugins, Templates)
  • Tag-based access control system
  • Real-time updates via WebSocket
  • Plugin system for extensibility
  • Backup/restore functionality
  • Multi-tenant operation support

CI Validation:

  • Always ensure GitHub Actions pass before merging
  • Check test reports in GitHub Actions artifacts
  • Verify both unit tests and Gatling load tests complete successfully

Common Tasks

Development Workflow:

  1. Make code changes
  2. Quick validation (local): ./mvnw clean compile -- validates compilation in ~11 seconds
  3. Run specific test class (local): ./mvnw test -Dtest=YourTestClass
  4. Run application for manual testing: See "Running the Application" section
  5. Full test suite before committing: ./mvnw clean package -- ~85 seconds (or Docker: docker build --target test -t jasper-test . && docker run --rm jasper-test)

Troubleshooting:

Most Common Error: "release version 25 not supported" or "release version 21 not supported"

  • Cause: Java 25 (or Java 21+) is not in your PATH or JAVA_HOME is not set
  • Working Solution (tested): Set JAVA_HOME to Java 25:
    1. export JAVA_HOME=/usr/lib/jvm/temurin-25-jdk-amd64
    2. export PATH=$JAVA_HOME/bin:$PATH
    3. Verify: java -version (should show Java 25)
    4. Build: ./mvnw clean package
  • Fallback (if Java 25 not available): Use Java 21:
    1. sudo apt-get update && sudo apt-get install -y openjdk-21-jdk
    2. export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
    3. export PATH=$JAVA_HOME/bin:$PATH
    4. Build: ./mvnw clean package -Djava.version=21 (the -Djava.version=21 flag is required since pom.xml targets Java 25)
  • Why not change to Java 17?: This project supports Java 21 or newer and targets Java 25 - changing pom.xml to Java 17 will not work
    • Alternative: Use Docker build docker build -t jasper . (but may have PKIX certificate issues in some environments)

Other Common Issues:

  • Docker certificate error ("PKIX path building failed"): This is caused by the Java truststore in the Docker base image not trusting Maven Central certificates. The --network=host flag does NOT fix this. Use local Java 25 Maven build instead (see above). Note: This issue does not affect GitHub Actions CI.
  • If JavaScript tests fail: Install Bun with curl -fsSL https://bun.sh/install | bash OR use Docker build
  • If Python tests fail: Ensure Python 3 is installed (sudo apt install python3 python3-pip) OR use Docker build
  • If database connection fails: Ensure PostgreSQL container is running (docker compose up db -d)
  • If Maven hangs: Check network connectivity for dependency downloads. First Maven build downloads many dependencies which can take 5-10 minutes. Subsequent builds are faster (~11-85 seconds depending on scope).
  • If Docker build fails: Ensure Docker has enough disk space (docker system prune -a to clean up)

Performance Notes:

  • NEVER CANCEL builds or tests
  • Compilation alone: ~11 seconds (local, cached) or ~2-5 minutes (Docker with dependencies)
  • Full test suite: ~85 seconds (local) or ~5 minutes (Docker)
  • Docker build (all stages): ~2 minutes
  • Docker build (builder stage only): ~2 minutes
  • Gatling load tests: ~27 seconds
  • Application startup: ~22 seconds

Repository Structure

jasper/
├── .github/workflows/     # GitHub Actions CI/CD pipelines
├── .m2/settings.xml      # Maven settings (minimal)
├── docker/               # Docker configuration files
├── gatling/              # Load testing module (separate Maven project)
│   ├── docker-compose.yaml  # Load test environment
│   ├── docker-compose.sqlite.yaml  # SQLite load test environment
│   └── src/test/java/simulations/  # Gatling test scenarios
├── src/main/java/jasper/ # Main application source
│   ├── aop/              # Aspect-oriented programming
│   ├── client/           # External service clients
│   ├── component/        # Business logic components
│   ├── config/           # Spring configuration
│   ├── domain/           # JPA entities
│   ├── errors/           # Error handling
│   ├── management/       # Management endpoints
│   ├── plugin/           # Plugin system
│   ├── repository/       # Data access layer
│   ├── security/         # Authentication and authorization
│   ├── service/          # Service layer
│   ├── util/             # Utility classes
│   └── web/              # REST controllers
├── src/main/resources/   # Configuration and static resources
│   └── config/application-sqlite.yml  # SQLite runtime profile
├── src/test/java/        # Unit and integration tests
├── docker-compose.yaml   # Development environment
├── Dockerfile           # Multi-stage production build
└── pom.xml              # Maven configuration

Key Files:

  • src/main/java/jasper/JasperApplication.java - Main Spring Boot application
  • src/main/java/jasper/domain/ - Core entities (Ref, Ext, User, Plugin, Template)
  • src/main/java/jasper/security/Auth.java - Tag-based access control implementation
  • src/main/java/jasper/web/rest/ - REST API controllers
  • src/main/resources/config/application.yml - Main application configuration
  • docker-compose.yaml - Local development stack
  • .github/workflows/test.yml - Main CI pipeline

Important Dependencies:

  • Spring Boot 4.1.0 (Web MVC, JPA, Security, WebSocket, Actuator)
  • Spring Cloud 2025.1.2 (OpenFeign, Resilience4j, Kubernetes)
  • Java 25 (build target; Java 21 is the supported fallback with -Djava.version=21)
  • PostgreSQL 18 (primary development database)
  • SQLite JDBC 3.53.2.0 (embedded runtime and test database)
  • Redis (caching and messaging via Spring Integration)
  • Liquibase (database migrations)
  • Caffeine (local caching)
  • Bun 1.3.14 (JavaScript runtime in Docker images)
  • Gatling 3.15.1 (load testing)
  • Testcontainers 2.0.5 (integration testing)

Code Style Guidelines

Logging:

  • All origin-specific log messages must prefix the message with the origin: logger.info("{} Message", origin, ...)
  • The first placeholder {} should always be for the origin in multi-tenant operations
  • Example: logger.debug("{} Creating bulkhead with {} permits", origin, maxConcurrent)
  • This ensures consistent log filtering and debugging in multi-tenant environments

Locality:

  • Keep a readable single-use expression at its call site instead of extracting it into a temporary variable
  • Treat src/main/java/jasper/security/Auth.java as the authoritative security specification; avoid cosmetic refactors that reduce locality or obscure authorization decisions

Code Drift Check

When a branch already contains more than one commit, ALWAYS check for code drift before finishing. Code drift happens when a change is made and then undone in a later commit, but an irrelevant edit remains (e.g., leftover imports, renamed variables, reordered code, whitespace changes, or stray helper code from the reverted change). To check for drift:

  • Diff the full branch against the merge base (e.g., git diff $(git merge-base HEAD origin/master))
  • Review every hunk and confirm it is required by the task; remove any edits that no longer serve a purpose

Always reference this documentation when working with the Jasper codebase to ensure consistency and avoid common pitfalls.

Trust

Not scanned yet. Artifacts are graded after they are crawled, so a recently discovered one may have no result for a while.

Versions

  • git-789b837fcc582026-08-04