Skip to content
Open
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
3 changes: 2 additions & 1 deletion .well-known/agent-cards-v1.1.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"current_release": "v1.1.0",
"legacy_release": "v1.0.0 (archival compatibility only)",
"publish_state": "ready-to-pin",
"license": "Apache-2.0"
"license": "Apache-2.0",
"publication_model": "root-canonical-plus-derivative-dist-pin"
}
}
3 changes: 2 additions & 1 deletion .well-known/agent.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"current_release": "v1.1.0",
"legacy_release": "v1.0.0 (archival compatibility only)",
"publish_state": "ready-to-pin",
"license": "Apache-2.0"
"license": "Apache-2.0",
"publication_model": "root-canonical-plus-derivative-dist-pin"
}
}
1 change: 1 addition & 0 deletions ONBOARDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Do not add descriptive fields to current-line cards; if the detail is not a bind
- `v1.0.0` is superseded by `v1.1.0`.
- Keep `v1.0.0` artifacts only for archival compatibility.
- Do not use `v1.0.0` paths in new examples, new release work, or the main update flow.
- `scripts/archive/` contains historical migration helpers only; it is not part of the active validation or release path for `v1.1.0`.

## Update flow for the current line

Expand Down
19 changes: 12 additions & 7 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# Security Policy — Agent Cards
# Security Policy — CommandLayer Agent Cards

Report issues that could break discovery or routing, including:
Report suspected security issues to `dev@commandlayer.org`. Use that channel for issues that could let published Agent Cards, discovery descriptors, or integrity metadata misstate identity, routing, or release provenance.

- stale or mismatched card schema bindings
- stale `_shared` references in the current line
- incorrect `entry` URIs
- manifest / discovery drift
- checksum mismatches
Examples include:

- unauthorized or incorrect changes to current-line card bindings, schema URLs, or `entry` URIs
- manifest or discovery drift that could misroute clients
- checksum or release-bundle inconsistencies that could hide tampering
- schema or validation defects that could cause consumers to trust malformed artifacts

Please do not open a public issue for a suspected security problem before maintainers have had a chance to review it. Include the affected file or URL, the release line, the impact you see, and any reproduction or verification steps.

This repository is maintained by a small team, so response timing may vary. Maintainers will try to acknowledge credible reports and coordinate next steps as soon as practical, but no formal SLA is offered.
2 changes: 1 addition & 1 deletion SECURITY_PROVENANCE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Security & Provenance — CommandLayer Agent Cards

CommandLayer Agent Cards prove identity and routing intent. They do not prove execution success.
CommandLayer Agent Cards prove identity and routing intent. They do not prove execution success. Suspected security issues with published cards, discovery metadata, or release integrity should be reported privately to `dev@commandlayer.org` as described in `SECURITY.md`.

## Provenance model for v1.1.0

Expand Down
48 changes: 24 additions & 24 deletions checksums.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
d11253a619a5292e09896a55b24d916d503829a3c5eeaa3281edbac6d080ef64 .well-known/agent-cards-v1.1.0.json
c54994da020bbb504f9092074981bc75f4a2c6bd6a3e402681deebf659ffbe51 .well-known/agent.json
8cbbb8edf6b3ec2e65dc54ce5bdd467a63aaaad1d90bbd251a729b238ef56507 agents/v1.0.0/commercial/authorizeagent.eth.json
bfad808d0e3b107df59887c9684303b87b4867d9887c9b1a035ca8b33b115cca agents/v1.0.0/commercial/checkoutagent.eth.json
0bbd1601794b3d18f63fc331b55888cb083e0f1a37d14c3c79679c237ec0414b agents/v1.0.0/commercial/purchaseagent.eth.json
15062e72b528e2f66e58a3d83ea617a4d9e699cb1eb25a0576cbf09f3808425d agents/v1.0.0/commercial/shipagent.eth.json
4079b22e3821dbfc141b1c9baaaf1cefb20b4c68af58725aacf8428e05d2e91a agents/v1.0.0/commercial/verifyagent.eth.json
3e4062b94bfb8cfc2bbf5de5ccdcbc620d5282de5ba7caab10dd0e1a60052183 .well-known/agent-cards-v1.1.0.json
8654b246656d035a9a4c171e9b773615ca362cd746adfaed377175ca19888407 .well-known/agent.json
b7d185443a2efcf37f760f687b38963558dc82899fa249f6b0a43a6631ebb717 agents/v1.0.0/commercial/authorizeagent.eth.json
864bfc0467080e4ff6c1514f044449eed79790a5cab420588c052e6ff77c47aa agents/v1.0.0/commercial/checkoutagent.eth.json
0f718f2125c5e6b792c56156f7312e98b8ec7b6e53df24436423135f6ae4abca agents/v1.0.0/commercial/purchaseagent.eth.json
59c44856acc76e3ecbe79408048c41e236afe1d4e5f34c4615f42de83dcf7d60 agents/v1.0.0/commercial/shipagent.eth.json
4d4f6f5b17a97db262af253d851dc29d32c9b049749ae546c8774a0db59fee2b agents/v1.0.0/commercial/verifyagent.eth.json
2b14d78ad82435da6846e119bc9bf82f5b7661ccef53f4b7c25aaa50411d8812 agents/v1.0.0/commons/analyzeagent.eth.json
acb40f650362582daedda35fd1dbd78b7d1b6866e26cb3ee8ca090e0d18331e1 agents/v1.0.0/commons/classifyagent.eth.json
88943a385de72550bbd7454ddc8aabc6b4bc101449b571a1966e9e8c8266040e agents/v1.0.0/commons/cleanagent.eth.json
Expand Down Expand Up @@ -36,30 +36,30 @@ d3cde6eef58761fe5b88e3df5cb448002a289735df8f1c164fdc3b74193c61b9 dist-pin/agent
10c6ca12542dbdb21ccb1816ba7c98704789729e016b8dafe5ee2361f8b0e75c dist-pin/agent-cards/v1.0.0/meta/manifest.json
d11253a619a5292e09896a55b24d916d503829a3c5eeaa3281edbac6d080ef64 dist-pin/agent-cards/v1.1.0/.well-known/agent-cards-v1.1.0.json
c54994da020bbb504f9092074981bc75f4a2c6bd6a3e402681deebf659ffbe51 dist-pin/agent-cards/v1.1.0/.well-known/agent.json
9f37939c58430df6efc118ec62e56d758a2c63ff6becc33b72056dff0abd01e4 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/authorizeagent.eth.json
0c2fb22fe4d5028b3218edfbc6783fa928df09c33cac3e4ae19dd6b4fb3b1d25 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/checkoutagent.eth.json
b92447ac389a28dd6d7bb9e48b62b4dcfe2d573db9e8e46769ff7f05b70c174c dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/purchaseagent.eth.json
8845af9bfb06aae06fff06d7926417e532e417faf8b11e8d906b54769f180684 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/shipagent.eth.json
0d6ee78a0a977601d2544feed5f483d193b2d5e0790417725d1665a0e6859538 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/verifyagent.eth.json
e1b3893660ea726ff444392df7abb2eada8b7a0e89e3d18fa1da3247e2546ba9 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/analyzeagent.eth.json
66ae37ace0e04714b1965c7661237843dc699e3e2d1f68620cff45f1132fe81f dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/classifyagent.eth.json
1b56892f20d39d4780a49b8f96dd769fa7d2178f9cb04fe3c60f78d726c1889e dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/cleanagent.eth.json
eb575e806ce80fb473d771e667caa96e4e01806345292408882c92de54f2e059 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/convertagent.eth.json
0d25e3b86ca25c333a17a0cc4b9a1e0b5265dbe2bc13d88ab9da220eb5f1b613 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/describeagent.eth.json
6459519e39a9107e4294a8ad5bb46ba091933823145853aba50f38a283fbd167 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/explainagent.eth.json
60288c4c63ceb7936df2dc686b063c0b97f714afac3662f05a9f10da0b6043c4 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/fetchagent.eth.json
2c6a69e8e91d712c09994547a42bfb4043cd5abd14df2ac3f43f4d8837d2e433 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/formatagent.eth.json
7ff9756b5bcc1f989c0f36b76de8d0a8fa2d5287532dfe9717c9622eac5f6c64 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/parseagent.eth.json
1ee1a0b04cbc2488fea75458f34b0b271b7801d8e01533e4ba5dd91f2aa9ae15 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/summarizeagent.eth.json
d12610ea54b31b80758fbc68fcfaf8f20e5588097630f7d04a552bde1be458b1 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/authorizeagent.eth.json
0c7834aaf6d0692d2db9f29862ce2ae25b987cc41926bd242706da7b2847f21a dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/checkoutagent.eth.json
584a77bb4c75dc84f9e4ddf5d700a0ef2183777acd4cdf2c1761998cb2565d22 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/purchaseagent.eth.json
693f5f5cdafd76dac147f74a5c93901724b9c40a90360e28999b2cdf81e20d04 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/shipagent.eth.json
406ce4409b3a86678b95f765d4c4ecdc62dc2d735cc1c2823b149ae6743b6fc2 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commercial/verifyagent.eth.json
830324fb1fbdbc5f0796a8c87cd63683067b585e4cb73a5cd6c1563040df1d97 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/analyzeagent.eth.json
d2b00f033bdaeff370f77db9550715a8dad2c65b2c26866d9f2f75920c7500b6 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/classifyagent.eth.json
9086b5a11dc5353489946450dc3ee2d7621c042a8fee950c120b416103c8bcd2 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/cleanagent.eth.json
eeff77968e928f63329abd0839666b217651cfb4204c21a603b4dfbe707d086d dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/convertagent.eth.json
1d9f4558935cf437f860b571525850a44e522bac4590daff7dcb4917f7759edb dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/describeagent.eth.json
429fcf341f5c0d8edafbbe450f2c43b19b901b3e46d754c6f59fd046202a3aaf dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/explainagent.eth.json
73a278788f121c0c84db48ffaea900b529f57cc872afb3310bb269ebbb7e0d52 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/fetchagent.eth.json
84aca63347052d746c4c87121fa5705847844786cb521e2c6d6ad85a272df97e dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/formatagent.eth.json
f45b8bb7f745af38fce9a78c1d3a40d36a558e0c4716f59f8e70e561c89ae4e6 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/parseagent.eth.json
315eedad7b1bd8559efa8d3bdf8567c1af7b241be1c934e2ca1dfd90059d90c8 dist-pin/agent-cards/v1.1.0/agents/v1.1.0/commons/summarizeagent.eth.json
44f61b49522db5b0d058a57f4397058b3a95e1688ff6f9fd76804b2e7b46a00f dist-pin/agent-cards/v1.1.0/meta/commercial-agent.json
7493cef19304e6dc4f8991f11fdcd70d75b21e1c396684e614ead00d0892f407 dist-pin/agent-cards/v1.1.0/meta/commons-agent.json
e25e455f827f166c1168dc56582ef47e6fb83fd252bca0c0e8fe0f7feba0fa7c dist-pin/agent-cards/v1.1.0/meta/manifest.json
b7b573a464b3ba9f643958b716e72ce9eeb095a7c5b87bf2620eb53e7dc6afb3 dist-pin/agent-cards/v1.1.0/schemas/v1.1.0/agent.card.schema.json
0735b66ce8352a56cb18b22f60393dc669f323bcaf8e44aa1ce797e2274d524c dist-pin/agent-cards/v1.1.0/schemas/v1.1.0/agent.descriptor.schema.json
6e082c065b0ab5365b0fe3424062855587e6226a06b5ee092d77f91ea829afe2 dist-pin/agent-cards/v1.1.0/schemas/v1.1.0/agent.descriptor.schema.json
44f61b49522db5b0d058a57f4397058b3a95e1688ff6f9fd76804b2e7b46a00f meta/commercial-agent.json
7493cef19304e6dc4f8991f11fdcd70d75b21e1c396684e614ead00d0892f407 meta/commons-agent.json
e25e455f827f166c1168dc56582ef47e6fb83fd252bca0c0e8fe0f7feba0fa7c meta/manifest.json
ec6b2669daca50f99c9b8e04db7b8010169786788431cd74b68e547441216b8a schemas/v1.0.0/_shared/agent.card.base.schema.json
c22100701ae9ebad97cfc1cb468a0369e424a0cdcec2d62968b848ef5d14369c schemas/v1.0.0/_shared/agent.descriptor.schema.json
ffc066f827668ccc28b29efaf6b75def28b4931227545a6210e9faee8c4527c2 schemas/v1.1.0/agent.card.schema.json
0735b66ce8352a56cb18b22f60393dc669f323bcaf8e44aa1ce797e2274d524c schemas/v1.1.0/agent.descriptor.schema.json
6e082c065b0ab5365b0fe3424062855587e6226a06b5ee092d77f91ea829afe2 schemas/v1.1.0/agent.descriptor.schema.json
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"license": "Apache-2.0",
"author": "Gregory Soucy",
"type": "module",
"engines": {
"node": ">=22 <23"
},
"keywords": [
"agent",
"agents",
Expand Down Expand Up @@ -43,7 +46,7 @@
"validate:current": "node scripts/validate-cards.mjs --mode=current",
"validate:legacy": "node scripts/validate-cards.mjs --mode=legacy",
"validate:checksums": "node scripts/generate-checksums.mjs --verify",
"validate": "npm run validate:cards && npm run validate:checksums"
"validate": "npm run validate:current && npm run validate:checksums"
},
"devDependencies": {
"ajv": "^8.17.1",
Expand Down
58 changes: 48 additions & 10 deletions scripts/validate-cards.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import addFormats from "ajv-formats";
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
const ROOT = path.join(__dirname, "..");
const CURRENT_LINE = "v1.1.0";
const LEGACY_LINE = "v1.0.0";
const CARD_HTTP_ROOT = `https://commandlayer.org/agent-cards/agents/${CURRENT_LINE}`;
const LEGACY_PLACEHOLDER_PATTERNS = ["example.com", "example.org", "TODO", "REPLACE_ME"];

const commonsVerbs = ["analyze", "classify", "clean", "convert", "describe", "explain", "fetch", "format", "parse", "summarize"];
const commercialVerbs = ["authorize", "checkout", "purchase", "ship", "verify"];
Expand All @@ -16,12 +18,30 @@ const expectedV11 = {
commercial: commercialVerbs.map((verb) => `${verb}agent.eth.json`)
};

const SOURCE_ROOTS = {
[CURRENT_LINE]: {
commons: `https://raw.githubusercontent.com/commandlayer/protocol-commons/refs/tags/${CURRENT_LINE}/schemas/${CURRENT_LINE}/commons`,
commercial: `https://raw.githubusercontent.com/commandlayer/protocol-commercial/refs/tags/${CURRENT_LINE}/schemas/${CURRENT_LINE}/commercial`
},
[LEGACY_LINE]: {
commons: "https://commandlayer.org/schemas/v1.0.0/commons",
commercial: "https://commandlayer.org/schemas/v1.0.0/commercial"
}
};

const MIRROR_ROOTS = {
[CURRENT_LINE]: {
commons: `https://commandlayer.org/schemas/${CURRENT_LINE}/commons`,
commercial: `https://commandlayer.org/schemas/${CURRENT_LINE}/commercial`
}
};

const ajv = new Ajv2020({ strict: true, allErrors: true });
addFormats(ajv);

function getMode() {
const arg = process.argv.find((value) => value.startsWith("--mode="));
const mode = arg ? arg.split("=")[1] : "release";
const mode = arg ? arg.split("=")[1] : "current";
if (!["current", "legacy", "release"].includes(mode)) {
throw new Error(`Unsupported validation mode: ${mode}`);
}
Expand Down Expand Up @@ -122,6 +142,8 @@ function validateCard(fullPath) {

if (folderVersion === CURRENT_LINE) {
const expectedSchema = `https://commandlayer.org/agent-cards/schemas/${CURRENT_LINE}/agent.card.schema.json`;
const expectedSourceRoot = SOURCE_ROOTS[CURRENT_LINE][tier];
const expectedMirrorRoot = MIRROR_ROOTS[CURRENT_LINE][tier];
if (card.$schema !== expectedSchema) fail(`${relativePath}: stale or invalid $schema.`);
if (JSON.stringify(card).includes("_shared")) fail(`${relativePath}: current ${CURRENT_LINE} card must not reference _shared.`);

Expand All @@ -138,9 +160,9 @@ function validateCard(fullPath) {
}
}

if (folderVersion === "v1.0.0") {
if (folderVersion === LEGACY_LINE) {
const text = JSON.stringify(card);
const placeholder = PLACEHOLDER_PATTERNS.find((pattern) => text.includes(pattern));
const placeholder = LEGACY_PLACEHOLDER_PATTERNS.find((pattern) => text.includes(pattern));
if (placeholder) fail(`${relativePath}: contains legacy placeholder content (${placeholder}).`);
}

Expand All @@ -154,8 +176,8 @@ function validateManifestAgainstCards(cardRecords) {
const manifestMap = new Map();

for (const entry of manifest.entries) {
const url = new URL(entry.agent_card);
const relativePath = decodeURIComponent(url.pathname.replace(/^\/agent-cards\//, ""));
const parsedUrl = new URL(entry.agent_card);
const relativePath = decodeURIComponent(parsedUrl.pathname.replace(/^\/agent-cards\//, ""));
if (manifestMap.has(relativePath)) fail(`meta/manifest.json: duplicate manifest entry for ${relativePath}.`);
manifestMap.set(relativePath, entry);

Expand Down Expand Up @@ -187,7 +209,7 @@ function validateManifestAgainstCards(cardRecords) {

expectEqual(manifest.entries.length, cardRecords.length, "meta/manifest.json: entry count must match indexed current-line cards.");
expectEqual(manifest.release_lines.current, CURRENT_LINE, "meta/manifest.json: current release line mismatch.");
expectEqual(manifest.roots.cards_http, CARD_HTTP_ROOT, "meta/manifest.json: cards_http root mismatch.");
expectEqual(manifest.roots.canonical_cards_http, CARD_HTTP_ROOT, "meta/manifest.json: canonical_cards_http root mismatch.");
expectEqual(manifest.updated_at, "2026-03-19T00:00:00Z", "meta/manifest.json: updated_at must reflect the current release stamp.");

const commonsCount = cardRecords.filter(({ tier }) => tier === "commons").length;
Expand All @@ -198,17 +220,33 @@ function validateManifestAgainstCards(cardRecords) {
console.log("✅ Manifest aligned with current-line card files: meta/manifest.json");
}

function validateCurrentLine() {
console.log("▶ Validating current canonical release line (v1.1.0).");
function validateCurrentLine(mode) {
console.log(`▶ Validating ${mode === "release" ? "release" : "current canonical"} line (${CURRENT_LINE}).`);
validateDescriptor(".well-known/agent.json");
validateDescriptor(".well-known/agent-cards-v1.1.0.json");
validateExpectedV11Set();
const cardRecords = [];
for (const file of collectJsonFiles("agents")) {
for (const file of collectJsonFiles(path.join("agents", CURRENT_LINE))) {
const record = validateCard(file);
if (record?.relativePath.startsWith(`agents/${CURRENT_LINE}/`)) cardRecords.push(record);
if (record) cardRecords.push(record);
}
validateManifestAgainstCards(cardRecords);
}

function validateLegacyLine() {
console.log(`▶ Validating legacy compatibility line (${LEGACY_LINE}).`);
for (const file of collectJsonFiles(path.join("agents", LEGACY_LINE))) {
validateCard(file);
}
}

function main() {
const mode = getMode();
if (mode === "legacy") {
validateLegacyLine();
} else {
validateCurrentLine(mode);
}
if (process.exitCode) process.exit(process.exitCode);
console.log(`✅ ${mode === "release" ? "Release" : mode[0].toUpperCase() + mode.slice(1)} validation completed successfully.`);
}
Expand Down