This page shows the full end-to-end flow that a wafpass-server performs when it submits a validation run to the WAF++ validation gateway.

The gateway is the central trust anchor: it issues sub-CA certificates to trusted servers, receives signed validation runs, verifies them, and returns an official validation envelope that any third party can verify against the gateway root CA.

1. Server certificate (issued earlier)

Before a server can submit anything, an administrator registers it in the gateway admin UI and issues a sub-CA certificate. The server stores the private key securely and sends only the certificate with each submission.

curl -X POST https://validate.waf2p.dev/api/admin/server-certs \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "server_id": "acme-prod-1",
    "server_public_key_pem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
    "validity_days": 365
  }'

The returned certificate is stored on the server as server.crt.

2. Build a local attestation

The server runs the WAF++ checks locally and signs the canonical run hash with its own Ed25519 attestation key (the private counterpart of the public key that was registered with the gateway).

wafpass check ./infra --output json --project acme-platform/prod --branch main

This produces a run JSON. The server then computes:

canonical_hash = sha256(canonicalize(run_json)).hexdigest()
signature = ed25519_sign(canonical_hash, server_attestation_private_key)

3. Submit to the gateway

The server POSTs the full payload to the gateway. You can download the exact example body used below:

Download example payload JSON

Request

curl -X POST https://validate.waf2p.dev/api/v1/validations \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: wafpass_..." \
  --data-binary @wafpp-submit-payload.json

Request body

{
  "server_certificate": "-----BEGIN CERTIFICATE-----\nMIIBkTCB+wIJAKHBfpEaq3YDMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBndh\nZnBhc3MwHhcNMjYwODE2MDYwMDAwWhcNMjcwODE2MDYwMDAwWjARMQ8wDQYDVQQD\nDAZ3YWZwYXNzMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHBfpEaq3YDMqWh7pEy\n8xQH1vLWNV8j7Y7BgQKpkCM+wPFuqeM8J8bAqWh7pE3y8xQH1vLWNV8j7Y7BgQKp\nkCMDH1sCAwEAATANBgkqhkiG9w0BAQsFAANBAF8Q1vLWNV8j7Y7BgQKpkCM+wPFu\nqeM8J8bAqWh7pE3y8xQH1vLWNV8j7Y7BgQKpkCM+wPFuqeM8J8bAqWh7pE3y8xQ=\n-----END CERTIFICATE-----",
  "local_attestation": {
    "canonical_hash": "7184231525be8173ccb7eb0b5fc804630e37c49c2ec3c511b3c47b8d875a54a6",
    "public_key": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAwPFuqeM8J8bAqWh7pE3y8xQH1vLWNV8j7Y7BgQKpkCM=\n-----END PUBLIC KEY-----",
    "signature": "f8c3b2a1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
    "algorithm": "Ed25519"
  },
  "run": {
    "project": "acme-platform/prod",
    "target_url": "https://api.acme.example.com",
    "started_at": "2026-08-16T11:42:00Z",
    "finished_at": "2026-08-16T11:43:12Z",
    "checks": [
      {
        "id": "waf-ctl-001",
        "control": "Encrypt data at rest",
        "status": "pass",
        "severity": "critical",
        "resource": "aws_rds_cluster.primary",
        "message": "Storage encryption is enabled with AWS managed KMS key."
      },
      {
        "id": "waf-ctl-042",
        "control": "Restrict inbound network access",
        "status": "pass",
        "severity": "critical",
        "resource": "aws_security_group.app",
        "message": "Only ports 443 and 80 are open to the load balancer security group."
      },
      {
        "id": "waf-ctl-017",
        "control": "Enable audit logging",
        "status": "fail",
        "severity": "high",
        "resource": "aws_s3_bucket.logs",
        "message": "Object-level logging is not configured for this bucket."
      }
    ]
  }
}

4. Gateway response

If the server certificate is valid and registered, and the local attestation verifies, the gateway signs the canonical run hash with its intermediate CA and returns the official validation envelope.

Download example response JSON

{
  "id": "waf-ex-12345678-1234-1234-1234-123456789abc",
  "validation_id": "waf-ex-12345678-1234-1234-1234-123456789abc",
  "status": "valid",
  "server_id": "acme-prod-1",
  "canonical_hash": "7184231525be8173ccb7eb0b5fc804630e37c49c2ec3c511b3c47b8d875a54a6",
  "signed_at": "2026-08-16T11:43:15.000000Z",
  "server_public_key": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAwPFuqeM8J8bAqWh7pE3y8xQH1vLWNV8j7Y7BgQKpkCM=\n-----END PUBLIC KEY-----",
  "server_signature": "f8c3b2a1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
  "certificate_chain": [
    "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
  ],
  "verify_url": "https://validate.waf2p.dev/api/v1/validations/waf-ex-12345678-1234-1234-1234-123456789abc/verify",
  "badge_url": "https://validate.waf2p.dev/api/v1/validations/waf-ex-12345678-1234-1234-1234-123456789abc/badge.svg"
}

5. Verify the validation

Anyone can verify the result without trusting the submitting server:

curl https://validate.waf2p.dev/api/v1/validations/waf-ex-12345678-1234-1234-1234-123456789abc/verify

The gateway checks the certificate chain against its root CA, verifies the canonical hash, and returns the current status (valid or revoked).

6. Live local example

This flow was executed against the development gateway running at http://localhost:8001:

# 1. Run the WAF++ checks
wafpass check \
  --controls-dir ./controls \
  --project wafpass-live-example \
  --output json \
  --no-state \
  main.tf

# 2. Request official validation
wafpass validate official \
  --validation-url http://localhost:8001/api/v1/validations \
  --api-key wafpass_9TYsIJ9gPKzAE152DxYgaBYmxK-7w5OrG_ekaVMAaUk \
  --server-certificate /tmp/live-server.crt \
  /tmp/wafpass-result.json

Resulting validation:

Field Value
Validation ID e59c8ab3-f969-44be-867d-8c9e88bd7317
Canonical hash 98fa6a9776401d839cbd136d82d4edbda97e31e4757a04d8cc688e47659d6521
Status valid
Verification URL http://localhost:8001/api/v1/validations/e59c8ab3-f969-44be-867d-8c9e88bd7317/verify
Badge URL http://localhost:8001/api/v1/validations/e59c8ab3-f969-44be-867d-8c9e88bd7317/badge.svg
# Local offline verification
wafpass verify /private/tmp/wafpass-validation-98fa6a9776401d83.json
# → ✓ Local verification passed  envelope verified

# Public gateway verification
curl http://localhost:8001/api/v1/validations/e59c8ab3-f969-44be-867d-8c9e88bd7317/verify

See the rendered certificate →