Skip to content

API — Chaos control (admin)

This page documents all chaos administration endpoints used by the instructor. It covers seven controllers — a unified facade to drive and observe the 6 chaos families.

Controllers covered

Controller Prefix Chaos family
ChaosController /api/admin/chaos Performance (backend infrastructure)
BusinessChaosController /api/admin/chaos/business and /api/chaos/public/business Business (A1–A16)
FunctionalChaosController /api/admin/chaos/functional and /api/chaos/public/functional Functional (F1–F4)
SecurityChaosController /api/admin/chaos/security and /api/chaos/public/security Security (S1–S12)
ChaosScriptingController /api/admin/chaos/scripting Scripting
ChaosScriptingPublicController /api/chaos/public/scripting Scripting (public read)
FrontendChaosController /api/chaos/frontend Frontend (browser)

The student page (ChaosStudentController — pedagogical journeys and self-service control) is in chaos-student.md and pedagogique.md.


Cross-cutting principles

Authentication

All admin endpoints (prefixes /api/admin/chaos/*) require admin authentication:

  • Session cookie (admin_logged_in = true) OR
  • X-Admin-Token: <uuid> header

The check is centralized by AdminAuth.isAdmin(session, token) — see admin.md.

Public read endpoints

All /api/chaos/public/* endpoints are read-only and require no authentication. They are intended for student monitoring — allowing the monitoring interface to keep displaying chaos state even without admin login.

These endpoints are excluded from the ChaosInterceptor — they always respond, even when performance chaos is active at saturation. This is a critical property: without this exclusion, a student would lose observability at the very moment they need it most.

Chaos level model

The vast majority of chaos use the same 0 to 4 level model:

Level Name Behavior
0 Disabled Nominal behavior
1 Junior First anomaly introduced
2 Intermediate Cumulative anomalies
3 Expert Advanced anomalies
4 Master Maximum level (requires Pro license)

Performance chaos (infrastructure) instead uses intensities 0-100 per component (CPU, memory, DB pool, etc.) — see below.

Standard response format

{
  "success": true,
  "message": "...",
  "status": { /* full chaos state */ }
}

Errors follow the PerfShop global format ({"error": "..."}) — see conventions.md.


Performance chaos — /api/admin/chaos

Performance chaos (backend infrastructure) is driven by intensity parameter and not by level, because each component is tuned independently. The ChaosController aggregates 8 distinct parameters.

Overview

Method Endpoint Description
GET /api/admin/chaos/status Full state (backend + frontend)
GET /api/admin/chaos/public/status Same, no auth (monitoring)
POST /api/admin/chaos/reset Resets all chaos to 0
POST /api/admin/chaos/cpu CPU saturation
POST /api/admin/chaos/memory Controlled memory leak
POST /api/admin/chaos/gc-pressure GC pressure (sawtooth pattern)
POST /api/admin/chaos/db-pool DB connection pool saturation
POST /api/admin/chaos/thread-pool Tomcat thread pool saturation
POST /api/admin/chaos/slow-queries SQL query slowdown
POST /api/admin/chaos/deadlock DB deadlock probability
POST /api/admin/chaos/network Network timeout simulation

Shared DTO — ChaosConfigRequest

All endpoints in this block share the same request DTO:

{
  "intensity": 80,
  "guardrail": 80,
  "ratio": 2
}
Field Type Required Constraint Usage
intensity Integer yes 0–105 Main intensity (0 = off, 100 = max, 105 = intentional OOM for memory)
guardrail Integer no 0–100 Memory safety cap (% of max heap) — default 80
ratio Integer no 1–5 CPU multiplier — number of concurrent threads

POST /api/admin/chaos/cpu

Generates CPU load via CpuChaosScheduler. Intensity represents a percentage of CPU time consumed, and ratio multiplies the number of load threads to saturate multiple cores.

Request

{ "intensity": 80, "ratio": 2 }

Response — 200 OK

{
  "success": true,
  "message": "CPU intensity set to 80 ratio=2x",
  "status": {
    "cpu": 80,
    "cpuRatio": 2,
    "memoryLeakTarget": 0,
    "memoryGuardrail": 80,
    "gcPressure": 0,
    "dbPool": 0,
    "threadPool": 0,
    "slowQueries": 0,
    "deadlock": 0,
    "network": 0
  }
}

The message is built from chaos.infra.cpu.set with the intensity and ratio values.


POST /api/admin/chaos/memory

Triggers a progressive memory leak via MemoryLeakSimulator. The intensity field is the target (in % of max heap), and guardrail is the safety cap beyond which the simulator refuses to allocate.

Request

{ "intensity": 90, "guardrail": 80 }

Special caseintensity: 105 triggers an intentional OOM (the simulator allocates beyond the max heap until OutOfMemoryError). This is reserved for recovery demonstrations and post-mortem heap dump analysis.

Effective formula

effectivePct = (intensity × guardrail) / 100

Example: intensity=90, guardrail=80 → heap target = 72% of max heap. This double constraint lets the instructor set the pedagogical target (intensity) and the safety target (guardrail) independently.

If intensity == 0, the simulator calls clearLeakedMemory() which progressively releases allocated memory.

Response — 200 OK

{
  "success": true,
  "message": "Memory leak target 90%, guardrail=80%",
  "status": { "memoryLeakTarget": 90, "memoryGuardrail": 80, "...": "..." }
}

If intensity == 105, the message becomes Memory leak target OOM, guardrail=80%.


POST /api/admin/chaos/gc-pressure

Activates the GcPressureSimulator which allocates short-lived objects to force the GC to work. The resulting pattern in Grafana is characteristic: sawtooth with a period of ~4 seconds (4-slot circular buffer × 1s retention).

Request

{ "intensity": 70 }

Response — 200 OK

{
  "success": true,
  "message": "GC pressure intensity set to 70",
  "status": { "gcPressure": 70, "...": "..." }
}

Recent catalog addition

The gc-pressure endpoint was added after the documentation overhaul prompts were written. It complements the traditional memory chaos: memory generates a linear leak (rising curve), gc-pressure generates a stable oscillation (sawtooth). Both can be combined to simulate a service under GC pressure and under memory leak.

If intensity == 0, the simulator calls clearBuffer() which empties the circular buffer.


POST /api/admin/chaos/db-pool

Saturates the HikariCP connection pool via DbPoolChaosScheduler. Intensity represents the % of connections permanently held by "dormant" ones that monopolize the pool without releasing.

Request

{ "intensity": 60 }

Response — 200 OK

{
  "success": true,
  "message": "DB pool saturation intensity set to 60",
  "status": { "dbPool": 60, "...": "..." }
}

POST /api/admin/chaos/thread-pool

Saturates the Tomcat thread pool. Incoming requests must wait for a thread to free up.

Request

{ "intensity": 80 }

Response — 200 OK

{
  "success": true,
  "message": "Thread pool saturation intensity set to 80",
  "status": { "threadPool": 80, "...": "..." }
}

POST /api/admin/chaos/slow-queries

Slows down certain SQL queries by inserting SLEEP()s or forcing the planner into full scans. Intensity is the probability that a query is slowed down and the duration of the slowdown.

Request

{ "intensity": 50 }

Response — 200 OK

{
  "success": true,
  "message": "Slow query intensity set to 50",
  "status": { "slowQueries": 50, "...": "..." }
}

POST /api/admin/chaos/deadlock

Injects a deadlock probability into concurrent transactions (typically on orders and order_items). Raises SQLIntegrityConstraintViolationException on the client side.

Request

{ "intensity": 30 }

Response — 200 OK

{
  "success": true,
  "message": "Deadlock intensity set to 30",
  "status": { "deadlock": 30, "...": "..." }
}

Deadlocks directly affect OrderController.getUserOrders() via applyDeadlockChaosPublic() — see orders.md.


POST /api/admin/chaos/network

Simulates network timeouts on outgoing calls (database, simulated external services). Intensity controls the probability and duration of slowdowns.

Request

{ "intensity": 40 }

Response — 200 OK

{
  "success": true,
  "message": "Network timeout intensity set to 40",
  "status": { "network": 40, "...": "..." }
}

GET /api/admin/chaos/status

Returns the consolidated backend + frontend state.

Auth: admin

Response — 200 OK

{
  "backend": {
    "cpu": 80,
    "cpuRatio": 2,
    "memoryLeakTarget": 0,
    "memoryGuardrail": 80,
    "gcPressure": 0,
    "dbPool": 0,
    "threadPool": 0,
    "slowQueries": 0,
    "deadlock": 0,
    "network": 0
  },
  "frontend": {
    "cpuBurn": 0,
    "memoryLeak": 0,
    "domFlood": 0,
    "fetchFlood": 0,
    "doubleFetch": 0
  }
}

GET /api/admin/chaos/public/status

Public endpoint (no authentication) returning the consolidated backend + frontend + business + functional state. Used by student monitoring.

Path under /admin but public

The endpoint is exposed under the prefix /api/admin/chaos/public/status — under /admin/ for routing consistency, but without auth. This choice seems counter-intuitive but it keeps all chaos statuses under a single tree in ChaosController.

Response — 200 OK

{
  "backend":    { "...": "..." },
  "frontend":   { "...": "..." },
  "business":   { "level": 0, "anomalies": [], "activeCount": 0 },
  "functional": { "level": 0, "anomalies": [], "activeCount": 0 }
}

POST /api/admin/chaos/reset

Resets all chaos to 0 in a single operation:

  • chaosService.resetAll() → backend infrastructure
  • memoryLeakSimulator.clearLeakedMemory() → releases leaked memory
  • gcPressureSimulator.clearBuffer() → empties the GC buffer
  • frontendChaosController.resetState() → resets frontend states
  • chaosScriptingService.resetAll() → clears scripting tokens
  • businessChaosService.reset() → business level → 0
  • securityChaosService.reset() → security level → 0
  • functionalChaosService.reset() → functional level → 0

Response — 200 OK

{
  "success": true,
  "message": "All chaos intensities reset to 0",
  "status": { /* full state at 0 */ }
}

DB reset not included

The reset does not modify the database. Modifications already applied by chaos (A15 history corruption, S12 superadmin promotion, A16 non-replenished stocks) remain persistent. A true "clean reset" additionally requires docker compose down -v to bring everything back to a fresh state.


Business chaos — /api/admin/chaos/business and /api/chaos/public/business

Business chaos is driven by a single parameter: the global level (0–4). Each level activates a cumulative set of A1–A16 anomalies. See the full list in chaos/business.md.

Overview

Method Endpoint Auth Description
POST /api/admin/chaos/business Admin Set the level (0-4)
GET /api/admin/chaos/business/status Admin Status + counters
POST /api/admin/chaos/business/reset Admin Reset level and counters
POST /api/admin/chaos/business/logs/clear Admin Empty the activity log
GET /api/chaos/public/business/status None Public status (monitoring)
GET /api/chaos/public/business/logs None Public activity log
GET /api/chaos/public/business/anomalies None Pedagogical catalog for a level

POST /api/admin/chaos/business

Request

{ "level": 3 }

Response — 200 OK

{
  "success": true,
  "status": {
    "level": 3,
    "levelName": "Level 3 — Expert",
    "anomaliesActive": ["A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10", "A11"],
    "counters": {
      "A1": 0, "A2": 0, "A3": 0, "A4": 0, "A5": 0,
      "A6": 0, "A7": 0, "A8": 0, "A9": 0, "A10": 0, "A11": 0
    }
  }
}

Error codes

Code Cause
400 Level outside [0–4] (chaos.error.level_range)
401 Not authenticated

GET /api/chaos/public/business/anomalies

Pedagogical catalog: returns the list of anomalies active for a given level, with their localized descriptions.

Parameters

Parameter Type Default Description
level (query) integer 3 Level to retrieve the catalog for

Response — 200 OK

{
  "level": 3,
  "levelName": "Level 3 — Expert",
  "count": 11,
  "anomalies": [
    { "id": "A1", "name": "Incorrect VAT", "detail": "VAT rate 19.6% applied instead of 20% — total amount slightly underestimated" },
    { "id": "A11", "name": "Session token not invalidated", "detail": "Token valid 30s after logout — replay attack possible" }
  ]
}

This endpoint is used by the student monitoring frontend to display the pedagogical sheet for each level.


Functional chaos — /api/admin/chaos/functional and /api/chaos/public/functional

Same model as Business chaos, with 4 F1–F4 anomalies instead of 16.

Overview

Method Endpoint Description
POST /api/admin/chaos/functional Set level
GET /api/admin/chaos/functional/status Status
POST /api/admin/chaos/functional/reset Reset
POST /api/admin/chaos/functional/logs/clear Empty log
GET /api/chaos/public/functional/status Public status
GET /api/chaos/public/functional/logs Public log
GET /api/chaos/public/functional/anomalies?level=N Catalog

Structure identical to Business chaos — see the examples above. The only difference is that level=4 includes F4 (silent corruption), the most vicious anomaly in the catalog. See chaos/functional.md.


Security chaos — /api/admin/chaos/security and /api/chaos/public/security

Same model, with 12 S1–S12 faults. Level 4 activates the S10/S11/S12 faults which make AdminPortalController visible and vulnerable — see admin-portal.md.

Overview

Method Endpoint Description
POST /api/admin/chaos/security Set level
GET /api/admin/chaos/security/status Status
POST /api/admin/chaos/security/reset Reset
POST /api/admin/chaos/security/logs/clear Empty log
GET /api/chaos/public/security/status Public status
GET /api/chaos/public/security/logs Public log
GET /api/chaos/public/security/faults?level=N Catalog

Level 4 = hidden portal active

Setting Security chaos to level 4 immediately activates AdminPortalController — the /api/admin/portal/* endpoints stop returning 404 and become exploitable. Dropping the level below 4 re-hides the portal.

Response of GET /public/security/faults?level=4

{
  "level": 4,
  "levelName": "Level 4 — Master",
  "count": 12,
  "faults": [
    { "id": "S1", "name": "SQL Injection", "detail": "Parameter q= injected in native SQL — /api/products/search" },
    { "id": "S12", "name": "IDOR Privilege Escalation", "detail": "PUT /api/admin/portal/accounts/{id}/promote — superAdmin check bypassable" }
  ]
}

Scripting chaos — /api/admin/chaos/scripting and /api/chaos/public/scripting

Scripting chaos controls the complexity of anti-replay headers required on the checkout journey. Level names follow a specific gradation, defined in the chaos.scripting.level.* i18n keys:

Level Name Required headers
0 Disabled None
1 Junior X-Session-Token, X-Request-ID
2 Intermediate + X-Action-Token renewed at each step
3 Expert + X-CSRF-Token, X-Step-Token, X-Signature (HMAC)
4 Maestro Same + HMAC key derived from sessionToken

Overview

Method Endpoint Auth Description
POST /api/admin/chaos/scripting Admin Set level (0-4)
GET /api/admin/chaos/scripting/status Admin Status + active bundles
POST /api/admin/chaos/scripting/reset Admin Clears all bundles
GET /api/admin/chaos/scripting/logs Admin Activity log
DELETE /api/admin/chaos/scripting/logs Admin Empty the log
GET /api/chaos/public/scripting/status None Public status
GET /api/chaos/public/scripting/logs None Public log

Separate public controller

Unlike other families where the same controller handles both admin and public routes, Scripting chaos uses two separate controllers:

  • ChaosScriptingController/api/admin/chaos/scripting (admin)
  • ChaosScriptingPublicController/api/chaos/public/scripting (public)

This split reflects a strict separation between the control interface and the monitoring interface.

POST /api/admin/chaos/scripting

Request

{ "level": 2 }

Response — 200 OK

{
  "success": true,
  "status": {
    "level": 2,
    "levelName": "Intermediate",
    "activeBundles": 0,
    "rotationCount": 0
  }
}

Error codes

Code Cause
400 Level outside [0–4] (chaos.scripting.error.level_range) — message: level must be 0, 1, 2, 3 or 4
401 Not authenticated

POST /api/admin/chaos/scripting/reset

Clears all active bundles (session tokens of all users in a checkout journey) and resets the level to 0.

Response — 200 OK

{
  "success": true,
  "message": "All scripting tokens cleared"
}

Immediate effect on students

A reset while a student is mid-checkout immediately breaks their session — the next step will return a Scripting chaos error (invalid token). This is acceptable in training since students can restart the journey, but should be avoided in a live demonstration without warning.


Frontend chaos — /api/chaos/frontend

Frontend chaos is handled by a relay controller: the backend only stores a state that is then polled by the React frontend every 5 seconds and interpreted browser-side.

Overview

Method Endpoint Auth Description
GET /api/chaos/frontend/state None Current state (polled by the frontend)
POST /api/chaos/frontend/state Admin State update

GET /api/chaos/frontend/state

Returns the current state of the 4 frontend chaos. Endpoint continuously polled by the React frontend, without authentication.

Response — 200 OK

{
  "cpuBurn": 0,
  "memoryLeak": 0,
  "domFlood": 0,
  "fetchFlood": 0,
  "doubleFetch": 0
}

Each value is an intensity 0–100.

Chaos Description
cpuBurn JavaScript loops that consume the browser CPU
memoryLeak Progressive allocation of un-released JS objects
domFlood Massive DOM element insertion
fetchFlood Multiplication of fetch() calls to /api/products
doubleFetch Systematic double-calling of requests (race conditions)

POST /api/chaos/frontend/state

Updates the frontend intensities.

Auth: admin

Request

{
  "cpuBurn": 50,
  "domFlood": 30
}

Only the keys transmitted are updated — the others keep their value. Values outside [0,100] are clamped:

state.put(k, Math.max(0, Math.min(100, v)));

Response — 200 OK

{
  "success": true,
  "state": {
    "cpuBurn": 50,
    "memoryLeak": 0,
    "domFlood": 30,
    "fetchFlood": 0,
    "doubleFetch": 0
  }
}

curl example — full control sequence

# 1. Admin login and token retrieval
TOKEN=$(curl -s -H "Content-Type: application/json" \
  -d '{"email":"admin@perfshop.fr","password":"admin"}' \
  http://localhost:9080/api/admin/login | jq -r '.adminToken')

# 2. Enable Performance chaos CPU at 80% with ratio 2
curl -H "X-Admin-Token: $TOKEN" -H "Content-Type: application/json" \
     -d '{"intensity":80,"ratio":2}' \
     http://localhost:9080/api/admin/chaos/cpu

# 3. Enable Business chaos level 3 (11 anomalies)
curl -H "X-Admin-Token: $TOKEN" -H "Content-Type: application/json" \
     -d '{"level":3}' \
     http://localhost:9080/api/admin/chaos/business

# 4. Enable Security chaos level 4 (activates hidden portal)
curl -H "X-Admin-Token: $TOKEN" -H "Content-Type: application/json" \
     -d '{"level":4}' \
     http://localhost:9080/api/admin/chaos/security

# 5. Enable Frontend chaos — CPU burn 50%
curl -H "X-Admin-Token: $TOKEN" -H "Content-Type: application/json" \
     -d '{"cpuBurn":50,"domFlood":30}' \
     http://localhost:9080/api/chaos/frontend/state

# 6. Check consolidated state
curl -H "X-Admin-Token: $TOKEN" http://localhost:9080/api/admin/chaos/status

# 7. Global reset when done
curl -H "X-Admin-Token: $TOKEN" -X POST \
     http://localhost:9080/api/admin/chaos/reset

Cross-cutting points of attention

Recommended reset order

For a complete reset, prefer POST /api/admin/chaos/reset which calls all individual resets in the right order. Per-family resets (business/reset, security/reset, etc.) do not touch performance chaos or the frontend — a partial reset can leave artifacts.

Reset does not touch the database

No reset endpoint modifies the database. Stock corrections (A16), account promotions (S12), history corruptions (A15) are persistent. Only docker compose down -v restores the initial state.

Observability: monitoring uses the public endpoints

The 4 chaos controllers (Performance, Business, Functional, Security) + Scripting expose /api/chaos/public/* endpoints that the student monitoring polls periodically. These endpoints are designed to be monitored without authentication — they only expose the chaos state, never sensitive data.