Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 64 additions & 19 deletions schemas/trust-verification/_shared/proof.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
],
"properties": {
"canonicalization": {
"const": "json.sorted_keys.v1"
"enum": [
"json.sorted_keys.v1",
"erc8211.merkle.v1"
]
},
"hash": {
"type": "object",
Expand All @@ -32,26 +35,68 @@
}
},
"signature": {
"type": "object",
"additionalProperties": false,
"required": [
"alg",
"value",
"kid"
],
"properties": {
"alg": {
"const": "Ed25519"
},
"value": {
"type": "string",
"minLength": 16
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"alg",
"value",
"kid"
],
"properties": {
"alg": {
"const": "Ed25519"
},
"value": {
"type": "string",
"minLength": 16
},
"kid": {
"type": "string",
"minLength": 1
}
}
},
"kid": {
"type": "string",
"minLength": 1
{
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"alg",
"value",
"kid",
"role"
],
"properties": {
"alg": {
"const": "Ed25519"
},
"value": {
"type": "string",
"minLength": 16
},
"kid": {
"type": "string",
"minLength": 1
},
"role": {
"type": "string",
"enum": [
"user",
"solver",
"relayer",
"agent",
"runtime",
"verifier"
]
}
}
}
}
}
]
}
}
}
36 changes: 36 additions & 0 deletions schemas/trust-verification/_shared/trace.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.commandlayer.org/schemas/v1.0.0/trust/_shared/trace.schema.json",
"title": "CLAS Trace",
"description": "Shared trace envelope for correlating requests and receipts across agents, hops, workflows, solver fills, and spans.",
"type": "object",
"additionalProperties": false,
"required": [
"trace_id"
],
"properties": {
"trace_id": {
"type": "string",
"maxLength": 128
},
"span_id": {
"type": "string",
"maxLength": 128
},
"parent_span_id": {
"type": "string",
"maxLength": 128
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"tags": {
"type": "object",
"additionalProperties": {
"type": "string",
"maxLength": 512
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions schemas/trust-verification/attest/attest.receipt.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions schemas/trust-verification/grant/grant.receipt.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions schemas/trust-verification/permit/permit.receipt.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions schemas/trust-verification/reject/reject.receipt.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions schemas/trust-verification/sign/sign.receipt.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions schemas/trust-verification/verify/verify.receipt.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
"properties": {
"proof": {
"$ref": "../_shared/proof.schema.json"
},
"trace": {
"$ref": "../_shared/trace.schema.json"
}
}
}
Expand Down
44 changes: 44 additions & 0 deletions scripts/validate-trust-verification-examples.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,69 @@ for (const verb of entries) {
const requestSchema = JSON.parse(fs.readFileSync(requestSchemaPath, 'utf8'));
const receiptSchema = JSON.parse(fs.readFileSync(receiptSchemaPath, 'utf8'));
const proofSchemaPath = path.join(baseDir, '_shared', 'proof.schema.json');
const traceSchemaPath = path.join(baseDir, '_shared', 'trace.schema.json');

if (!fs.existsSync(proofSchemaPath)) fail(`[${verb}] Missing shared schema: ${proofSchemaPath}`);
if (!fs.existsSync(traceSchemaPath)) fail(`[${verb}] Missing shared schema: ${traceSchemaPath}`);

requestSchema.$id ??= pathToFileURL(requestSchemaPath).href;
receiptSchema.$id ??= pathToFileURL(receiptSchemaPath).href;

const proofSchema = JSON.parse(fs.readFileSync(proofSchemaPath, 'utf8'));
const traceSchema = JSON.parse(fs.readFileSync(traceSchemaPath, 'utf8'));
proofSchema.$id ??= pathToFileURL(proofSchemaPath).href;
traceSchema.$id ??= pathToFileURL(traceSchemaPath).href;

ajv.addSchema(traceSchema);
ajv.addSchema(proofSchema);
ajv.addSchema(requestSchema);
ajv.addSchema(receiptSchema);

const validateRequest = ajv.getSchema(requestSchema.$id) || ajv.compile(requestSchema);
const validateReceipt = ajv.getSchema(receiptSchema.$id) || ajv.compile(receiptSchema);

const validateProof = ajv.getSchema(proofSchema.$id) || ajv.compile(proofSchema);
const metadataSchema = receiptSchema.properties?.metadata;
if (!metadataSchema) fail(`[${verb}] Receipt schema missing metadata property`);
const metadataSchemaResolved = JSON.parse(JSON.stringify(metadataSchema));
if (metadataSchemaResolved.properties?.proof?.$ref) metadataSchemaResolved.properties.proof.$ref = proofSchema.$id;
if (metadataSchemaResolved.properties?.trace?.$ref) metadataSchemaResolved.properties.trace.$ref = traceSchema.$id;
const validateMetadata = ajv.compile(metadataSchemaResolved);

const proofSingle = {
canonicalization: 'json.sorted_keys.v1',
hash: { alg: 'SHA-256', value: 'a'.repeat(64) },
signature: { alg: 'Ed25519', value: 'signaturevalue1234', kid: 'key-1' },
};
const proofMerkle = {
canonicalization: 'erc8211.merkle.v1',
hash: { alg: 'SHA-256', value: 'b'.repeat(64) },
signature: [
{ alg: 'Ed25519', value: 'signaturevalue1234', kid: 'key-1', role: 'solver' },
],
};

const schemaChecks = [
{ name: 'proof single-signature json.sorted_keys.v1', ok: validateProof(proofSingle) },
{ name: 'proof erc8211.merkle.v1 with signature role array', ok: validateProof(proofMerkle) },
{ name: 'metadata proof only', ok: validateMetadata({ proof: proofSingle }) },
{ name: 'metadata proof + trace', ok: validateMetadata({ proof: proofSingle, trace: { trace_id: 'trace-1', span_id: 'span-1' } }) },
{ name: 'metadata unknown extra field rejected', ok: !validateMetadata({ proof: proofSingle, extra: true }) },
];


let verbFailed = false;
process.stdout.write(`\n[${verb}]\n`);

for (const check of schemaChecks) {
const status = check.ok ? 'PASS' : 'FAIL';
process.stdout.write(` ${status} schema-check ${check.name}\n`);
if (!check.ok) {
verbFailed = true;
hasExpectationFailures = true;
}
}

for (const { file, schemaType, shouldPass } of EXPECTATIONS) {
const targetPath = path.join(examplesDir, file);
if (!fs.existsSync(targetPath)) fail(`[${verb}] Missing example file: ${targetPath}`);
Expand Down
Loading