# Running Solid Conformance Test Harness (CTH)
Step-by-step instructions for running the Solid Conformance Test Harness against this server.
## Prerequisites
- Node.js 18+
- Docker
- Port 4000 available
## Quick Start
```bash
# 1. Kill any existing server on port 4000
fuser -k 4000/tcp 2>/dev/null || true
# 2. Clean data directory
rm -rf data && mkdir data
# 3. Start server with IdP and content negotiation
JSS_PORT=4000 JSS_CONNEG=true JSS_IDP=true node bin/jss.js start &
# 4. Wait for server to be ready
sleep 3
curl -s http://localhost:4000/ > /dev/null && echo "Server ready"
# 5. Create test users
curl -s -X POST http://localhost:4000/.pods \
-H "Content-Type: application/json" \
-d '{"name": "alice", "email": "alice@example.com", "password": "alicepassword123"}'
curl -s -X POST http://localhost:4000/.pods \
-H "Content-Type: application/json" \
-d '{"name": "bob", "email": "bob@example.com", "password": "bobpassword123"}'
# 6. Create test container (required by CTH)
mkdir -p data/alice/cth-test
# 7. Run authentication tests (assumes test-subjects.ttl and cth.env exist - see Configuration Files below)
docker run --rm --network=host \
-v $(pwd)/test-subjects.ttl:/app/test-subjects.ttl \
--env-file cth.env \
-e SUBJECTS=/app/test-subjects.ttl \
solidproject/conformance-test-harness:latest \
--target="https://github.com/solid/conformance-test-harness/jss" \
--filter="authentication"
```
## Configuration Files
### Test Subjects File (test-subjects.ttl)
Create `test-subjects.ttl`:
```turtle
@base .
@prefix solid-test: .
@prefix doap: .
@prefix earl: .
@prefix xsd: .
a earl:Software, earl:TestSubject ;
doap:name "JavaScript Solid Server"@en ;
doap:release ;
doap:developer ;
doap:homepage ;
doap:description "A minimal, fast, JSON-LD native Solid server."@en ;
doap:programming-language "JavaScript"@en ;
solid-test:skip "acp", "wac", "wac-allow-public" .
doap:revision "0.0.14"@en ;
doap:created "2025-12-27"^^xsd:date .
```
### Environment File (cth.env)
Create `cth.env`:
```bash
SERVER_ROOT=http://localhost:4000
TEST_CONTAINER=/alice/cth-test/
RESOURCE_SERVER_ROOT=http://localhost:4000
LOGIN_ENDPOINT=http://localhost:4000/idp/credentials
SOLID_IDENTITY_PROVIDER=http://localhost:4000/
USERS_ALICE_IDP=http://localhost:4000/
USERS_BOB_IDP=http://localhost:4000/
USERS_ALICE_WEBID=http://localhost:4000/alice/#me
USERS_BOB_WEBID=http://localhost:4000/bob/#me
USERS_ALICE_USERNAME=alice@example.com
USERS_ALICE_PASSWORD=alicepassword123
USERS_BOB_USERNAME=bob@example.com
USERS_BOB_PASSWORD=bobpassword123
```
### Environment Variables Reference
| Variable | Description | Example |
|----------|-------------|---------|
| `SERVER_ROOT` | Server base URL | `http://localhost:4000` |
| `TEST_CONTAINER` | Path to test container | `/alice/cth-test/` |
| `SOLID_IDENTITY_PROVIDER` | IdP issuer URL (with trailing slash) | `http://localhost:4000/` |
| `USERS_ALICE_IDP` | Alice's IdP | `http://localhost:4000/` |
| `USERS_ALICE_WEBID` | Alice's WebID | `http://localhost:4000/alice/#me` |
| `USERS_ALICE_USERNAME` | Alice's email | `alice@example.com` |
| `USERS_ALICE_PASSWORD` | Alice's password | `alicepassword123` |
| `USERS_BOB_IDP` | Bob's IdP | `http://localhost:4000/` |
| `USERS_BOB_WEBID` | Bob's WebID | `http://localhost:4000/bob/#me` |
| `USERS_BOB_USERNAME` | Bob's email | `bob@example.com` |
| `USERS_BOB_PASSWORD` | Bob's password | `bobpassword123` |
| `SUBJECTS` | Path to test-subjects.ttl inside container | `/app/test-subjects.ttl` |
## Running Specific Test Suites
### Authentication Tests (6 scenarios)
```bash
docker run --rm --network=host \
--env-file cth.env \
-v $(pwd)/test-subjects.ttl:/app/test-subjects.ttl \
-e SUBJECTS=/app/test-subjects.ttl \
solidproject/conformance-test-harness:latest \
--target="https://github.com/solid/conformance-test-harness/jss" \
--filter="authentication"
```
**Expected result:** 6/6 scenarios passing
### All Protocol Tests
```bash
docker run --rm --network=host \
--env-file cth.env \
-v $(pwd)/test-subjects.ttl:/app/test-subjects.ttl \
-e SUBJECTS=/app/test-subjects.ttl \
solidproject/conformance-test-harness:latest \
--target="https://github.com/solid/conformance-test-harness/jss"
```
## Interpreting Results
### Success Output
```
scenarios: 6 | passed: 6 | failed: 0 | time: 0.6349
MustFeatures passed: 1, failed: 0
MustScenarios passed: 6, failed: 0
```
### Failure Output
```
scenarios: 6 | passed: 4 | failed: 2 | time: 0.7952
Then status 401
status code was: 200, expected: 401, response time in milliseconds: 15
```
## Troubleshooting
### "Cannot get ACL url for root test container"
The test container doesn't exist. Create it:
```bash
mkdir -p data/alice/cth-test
```
### "Failed to read WebID Document" (401)
The WebID profile is not publicly readable. Check that the pod's ACL allows public read on the container itself (but not necessarily on children).
### "NullPointerException" during authentication
Usually means the IdP isn't returning proper responses. Check:
1. Server is running with `--idp` flag
2. Issuer URL has trailing slash
3. Users were created with email and password
### "DPoP htu mismatch"
URL mismatch in DPoP proof validation. Check that issuer URL doesn't have double slashes.
### Token format errors
Ensure the server returns JWT access tokens with:
- `aud: "solid"` claim
- 3-part JWT format (header.payload.signature)
- `webid` claim
## Server Requirements for CTH
The server must support:
1. **Solid-OIDC Identity Provider**
- OIDC discovery at `/.well-known/openid-configuration`
- JWKS at `/.well-known/jwks.json`
- Dynamic client registration at `/idp/reg`
- Credentials endpoint at `/idp/credentials` (for programmatic login)
2. **DPoP Token Binding**
- RS256 and ES256 algorithms
- Proper `cnf.jkt` claim in tokens
3. **WWW-Authenticate Header**
- 401 responses must include `WWW-Authenticate: DPoP realm="..."`
4. **Container Creation via PUT**
- PUT to path ending with `/` creates container
5. **ACL Inheritance**
- Children should NOT inherit public read by default
- Only owner permissions should have `acl:default`
## Current CTH Status (v0.0.14)
| Test Suite | Status |
|------------|--------|
| Authentication | 6/6 passing |
| Protocol (other) | Not yet tested |
| WAC | Skipped |
| ACP | Skipped |