# Security Tests

### NFT-SEC-01: JWT Authentication Required on Protected Endpoints

**Summary**: Validate all protected endpoints reject requests without a valid JWT token.
**Traces to**: AC-14 (security — JWT auth on API)

**Steps**:

| Step | Consumer Action | Expected Response |
|------|----------------|------------------|
| 1 | POST /sessions with no Authorization header | HTTP 401 |
| 2 | GET /sessions/{id}/stream with no Authorization header | HTTP 401 |
| 3 | POST /sessions/{id}/anchor with no Authorization header | HTTP 401 |
| 4 | DELETE /sessions/{id} with no Authorization header | HTTP 401 |
| 5 | POST /objects/locate with no Authorization header | HTTP 401 |
| 6 | GET /health with no Authorization header | HTTP 200 (health is public) |

**Pass criteria**: All protected endpoints return 401; /health returns 200 without auth

---

### NFT-SEC-02: Expired JWT Token Rejection

**Summary**: Validate the system rejects expired JWT tokens.
**Traces to**: AC-14 (security)

**Steps**:

| Step | Consumer Action | Expected Response |
|------|----------------|------------------|
| 1 | Generate a JWT token with exp set to 1 hour ago | Expired token |
| 2 | POST /sessions with expired token in Authorization header | HTTP 401 |
| 3 | POST /objects/locate with expired token | HTTP 401 |

**Pass criteria**: Expired tokens are rejected with 401

---

### NFT-SEC-03: Invalid JWT Signature Rejection

**Summary**: Validate the system rejects JWT tokens signed with the wrong key.
**Traces to**: AC-14 (security)

**Steps**:

| Step | Consumer Action | Expected Response |
|------|----------------|------------------|
| 1 | Generate a JWT token with a different signing key | Invalid signature token |
| 2 | POST /sessions with invalid-signature token | HTTP 401 |

**Pass criteria**: Invalid-signature tokens are rejected with 401

---

### NFT-SEC-04: Malformed API Request Handling

**Summary**: Validate the system handles malformed API payloads without crashing or leaking internal details.
**Traces to**: AC-14 (security), AC-16 (API robustness)

**Steps**:

| Step | Consumer Action | Expected Response |
|------|----------------|------------------|
| 1 | POST /objects/locate with empty body | HTTP 422 with generic error (no stack trace) |
| 2 | POST /objects/locate with body `{"pixel_x": "not_a_number"}` | HTTP 422 with validation error |
| 3 | POST /sessions with body exceeding 1MB | HTTP 413 or 422 (no crash) |
| 4 | POST /sessions/{id}/anchor with body `{"lat": 999, "lon": 999}` | HTTP 422 (invalid coordinates) |
| 5 | Verify system continues operating after all malformed requests | GET /health returns 200 |

**Pass criteria**: All malformed requests return 4xx errors with safe error messages (no stack traces, no internal paths); system remains operational

---

### NFT-SEC-05: MAVLink Injection Resistance

**Summary**: Validate the system ignores unexpected or malformed MAVLink messages on the MAVLink channel.
**Traces to**: AC-15 (ground station commands), solution security analysis

**Steps**:

| Step | Consumer Action | Expected Response |
|------|----------------|------------------|
| 1 | Send unexpected MAVLink message types to the system's MAVLink port | System ignores (no crash, no state corruption) |
| 2 | Send malformed COMMAND_LONG with invalid lat/lon in re-localization hint | System rejects or ignores invalid coordinates |
| 3 | Verify GPS_INPUT output continues normally | No disruption |

**Pass criteria**: System ignores unexpected messages; continues normal operation; does not process invalid re-localization coordinates
