Skip to content

Hash Chain Verification

Verify the integrity of the audit log hash chain over a specified time window. The audit log is structured as a hash chain — each record contains the hash of the previous record — making it tamper-evident. This endpoint walks the chain and reports whether every link is valid.

Endpoint

GET /api/v1/audit/verify-chain

Required Role

ADMIN

Headers

HeaderValueRequired
AuthorizationBearer <token>Yes
X-Tenant-IDTenant identifier stringYes

Query Parameters

ParameterTypeRequiredDescription
startstringYesISO 8601 start timestamp (inclusive).
endstringYesISO 8601 end timestamp (inclusive).

Time Window Limit

The requested window (end minus start) must not exceed 30 days. Requests spanning a longer period will be rejected with 400 Bad Request.

Response Body

json
{
  "valid": true,
  "brokenAt": null,
  "reason": null,
  "recordsVerified": 4821
}
FieldTypeDescription
validbooleantrue if every record in the window forms an unbroken hash chain; false if any link is invalid or missing.
brokenAtstring | nullISO 8601 timestamp of the first record where the chain breaks. null when valid is true.
reasonstring | nullHuman-readable description of why the chain is broken. null when valid is true.
recordsVerifiednumberTotal number of audit records examined during verification.

HTTP Status Codes

StatusMeaning
200 OKVerification completed. Inspect valid to determine chain integrity.
400 Bad RequestMissing parameters, malformed timestamps, or requested window exceeds the 30-day limit.
401 UnauthorizedMissing or invalid bearer token.
403 ForbiddenToken is valid but the caller lacks the ADMIN role.
500 Internal Server ErrorUnexpected engine failure during verification.

Examples

bash
curl -X GET "https://policy.aster-lang.dev/api/v1/audit/verify-chain?start=2024-01-01T00:00:00Z&end=2024-01-31T23:59:59Z" \
  -H "Authorization: Bearer <token>" \
  -H "X-Tenant-ID: acme-corp"
js
const params = new URLSearchParams({
  start: '2024-01-01T00:00:00Z',
  end:   '2024-01-31T23:59:59Z',
});

const response = await fetch(
  `https://policy.aster-lang.dev/api/v1/audit/verify-chain?${params}`,
  {
    headers: {
      Authorization: 'Bearer <token>',
      'X-Tenant-ID': 'acme-corp',
    },
  }
);

const result = await response.json();

if (!result.valid) {
  console.error(`Chain broken at ${result.brokenAt}: ${result.reason}`);
}

Example Response — Valid Chain

json
{
  "valid": true,
  "brokenAt": null,
  "reason": null,
  "recordsVerified": 4821
}

Example Response — Broken Chain

json
{
  "valid": false,
  "brokenAt": "2024-01-14T08:22:11Z",
  "reason": "Hash mismatch: stored hash does not match recomputed hash for record id=a3f9c1d2",
  "recordsVerified": 512
}

Released under the MIT License.