{
  "schemaVersion": "1.0",
  "item": {
    "slug": "schemapin",
    "name": "SchemaPin",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/jaschadub/schemapin",
    "canonicalUrl": "https://clawhub.ai/jaschadub/schemapin",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/schemapin",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=schemapin",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "CHANGELOG.md",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/schemapin"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/schemapin",
    "agentPageUrl": "https://openagent3.xyz/skills/schemapin/agent",
    "manifestUrl": "https://openagent3.xyz/skills/schemapin/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/schemapin/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "SchemaPin Development Skills Guide",
        "body": "Purpose: This guide helps AI assistants quickly integrate SchemaPin into applications for cryptographic tool schema verification.\n\nFor Full Documentation: See the README, Technical Specification, and language-specific READMEs in each subdirectory."
      },
      {
        "title": "What SchemaPin Does",
        "body": "SchemaPin prevents \"MCP Rug Pull\" attacks by enabling developers to cryptographically sign their tool schemas (ECDSA P-256 + SHA-256) and clients to verify schemas haven't been tampered with. It uses Trust-On-First-Use (TOFU) key pinning and RFC 8615 .well-known endpoints for public key discovery.\n\nPart of the ThirdKey trust stack: SchemaPin (tool integrity) → AgentPin (agent identity) → Symbiont (runtime)"
      },
      {
        "title": "Python",
        "body": "pip install schemapin\n\nfrom schemapin.crypto import KeyManager, SignatureManager\nfrom schemapin.core import SchemaPinCore\n\n# Generate keys\nprivate_key, public_key = KeyManager.generate_keypair()\n\n# Sign a schema\ncore = SchemaPinCore()\ncanonical = core.canonicalize_schema(schema_dict)\nsignature = SignatureManager.sign_schema(private_key, canonical)\n\n# Verify\nis_valid = SignatureManager.verify_signature(public_key, canonical, signature)"
      },
      {
        "title": "JavaScript",
        "body": "npm install schemapin\n\nimport { KeyManager, SignatureManager, SchemaPinCore } from 'schemapin';\n\n// Generate keys\nconst { privateKey, publicKey } = KeyManager.generateKeypair();\n\n// Sign a schema\nconst core = new SchemaPinCore();\nconst canonical = core.canonicalizeSchema(schema);\nconst signature = await SignatureManager.signSchema(privateKey, canonical);\n\n// Verify\nconst isValid = await SignatureManager.verifySignature(publicKey, canonical, signature);"
      },
      {
        "title": "Go",
        "body": "go get github.com/ThirdKeyAi/schemapin/go@v1.3.0\n\nimport (\n    \"github.com/ThirdKeyAi/schemapin/go/pkg/core\"\n    \"github.com/ThirdKeyAi/schemapin/go/pkg/crypto\"\n)\n\n// Generate keys\nkm := crypto.NewKeyManager()\nprivKey, pubKey, _ := km.GenerateKeypair()\n\n// Sign a schema\nspc := core.NewSchemaPinCore()\ncanonical, _ := spc.CanonicalizeSchema(schema)\nsig, _ := crypto.NewSignatureManager().SignSchema(privKey, canonical)\n\n// Verify\nvalid, _ := crypto.NewSignatureManager().VerifySignature(pubKey, canonical, sig)"
      },
      {
        "title": "Rust",
        "body": "[dependencies]\nschemapin = \"1.3\"\n\nuse schemapin::crypto::{generate_key_pair, sign_data, verify_signature};\nuse schemapin::core::SchemaPinCore;\n\n// Generate keys\nlet key_pair = generate_key_pair()?;\n\n// Sign\nlet core = SchemaPinCore::new();\nlet canonical = core.canonicalize_schema(&schema)?;\nlet signature = sign_data(&key_pair.private_key_pem, &canonical)?;\n\n// Verify\nlet is_valid = verify_signature(&key_pair.public_key_pem, &canonical, &signature)?;"
      },
      {
        "title": "1. Schema Canonicalization",
        "body": "Schemas are canonicalized (deterministic JSON serialization with sorted keys) before hashing. This ensures identical schemas always produce the same hash regardless of key ordering."
      },
      {
        "title": "2. .well-known Discovery",
        "body": "Developers publish their public key at https://example.com/.well-known/schemapin.json:\n\nfrom schemapin.utils import create_well_known_response\n\nresponse = create_well_known_response(\n    public_key_pem=public_key_pem,\n    developer_name=\"Acme Corp\",\n    schema_version=\"1.2\",\n    revocation_endpoint=\"https://example.com/.well-known/schemapin-revocations.json\"\n)"
      },
      {
        "title": "3. TOFU Key Pinning",
        "body": "On first verification, the developer's public key fingerprint is pinned. Subsequent verifications reject different keys for the same domain — detecting key substitution attacks."
      },
      {
        "title": "4. Verification Workflows",
        "body": "Online (standard):\n\nworkflow = SchemaVerificationWorkflow(pin_store)\nresult = workflow.verify_schema(schema, signature, \"https://example.com\")\n\nOffline (v1.2.0 — no HTTP required):\n\nfrom schemapin.verification import verify_schema_offline, KeyPinStore\n\npin_store = KeyPinStore()\nresult = verify_schema_offline(\n    schema, signature_b64, domain, tool_id,\n    discovery_data, revocation_doc, pin_store\n)"
      },
      {
        "title": "Standalone Revocation Documents",
        "body": "from schemapin.revocation import (\n    build_revocation_document, add_revoked_key,\n    check_revocation, RevocationReason\n)\n\ndoc = build_revocation_document(\"example.com\")\nadd_revoked_key(doc, fingerprint, RevocationReason.KEY_COMPROMISE)\ncheck_revocation(doc, some_fingerprint)  # raises if revoked"
      },
      {
        "title": "Trust Bundles (Offline / Air-Gapped)",
        "body": "Pre-package discovery + revocation data for environments without internet:\n\nfrom schemapin.bundle import SchemaPinTrustBundle\n\nbundle = SchemaPinTrustBundle.from_json(bundle_json_str)\ndiscovery = bundle.find_discovery(\"example.com\")\nrevocation = bundle.find_revocation(\"example.com\")"
      },
      {
        "title": "Pluggable Discovery Resolvers",
        "body": "from schemapin.resolver import (\n    WellKnownResolver,    # HTTP .well-known lookups\n    LocalFileResolver,    # Local JSON files\n    TrustBundleResolver,  # In-memory trust bundles\n    ChainResolver,        # First-match fallthrough\n)\n\n# Chain: try bundle first, fall back to HTTP\nresolver = ChainResolver([\n    TrustBundleResolver.from_json(bundle_json),\n    WellKnownResolver(timeout=10),\n])"
      },
      {
        "title": "Resolver-Based Verification",
        "body": "from schemapin.verification import verify_schema_with_resolver\n\nresult = verify_schema_with_resolver(\n    schema, signature_b64, domain, tool_id,\n    resolver, pin_store\n)"
      },
      {
        "title": "SkillSigner — File-Based Skill Folder Signing",
        "body": "Sign entire skill directories (e.g., a folder containing SKILL.md) with ECDSA P-256. Produces a .schemapin.sig manifest alongside the files, proving no file has been tampered with.\n\nPython:\n\nfrom schemapin.skill import sign_skill, verify_skill_offline\n\n# Sign a skill directory\nsig = sign_skill(\"./my-skill/\", private_key_pem, \"example.com\")\n# Writes .schemapin.sig into ./my-skill/\n\n# Verify offline\nfrom schemapin.verification import KeyPinStore\nresult = verify_skill_offline(\"./my-skill/\", discovery_data, sig, revocation_doc, KeyPinStore())\n\nJavaScript:\n\nimport { signSkill, verifySkillOffline } from 'schemapin/skill';\n\nconst sig = await signSkill('./my-skill/', privateKeyPem, 'example.com');\nconst result = verifySkillOffline('./my-skill/', discoveryData, sig, revDoc, pinStore);\n\nGo:\n\nimport \"github.com/ThirdKeyAi/schemapin/go/pkg/skill\"\n\nsig, err := skill.SignSkill(\"./my-skill/\", privateKeyPEM, \"example.com\", \"\", \"\")\nresult := skill.VerifySkillOffline(\"./my-skill/\", disc, sig, rev, pinStore, \"\")\n\nRust:\n\nuse schemapin::skill::{sign_skill, verify_skill_offline};\n\nlet sig = sign_skill(\"./my-skill/\", &private_key_pem, \"example.com\", None, None)?;\nlet result = verify_skill_offline(\"./my-skill/\", &disc, Some(&sig), rev.as_ref(), Some(&pin_store), None);"
      },
      {
        "title": ".schemapin.sig Format",
        "body": "{\n  \"schemapin_version\": \"1.3\",\n  \"skill_name\": \"my-skill\",\n  \"skill_hash\": \"sha256:<root_hash>\",\n  \"signature\": \"<base64_ecdsa_signature>\",\n  \"signed_at\": \"2026-02-14T00:00:00Z\",\n  \"domain\": \"example.com\",\n  \"signer_kid\": \"sha256:<key_fingerprint>\",\n  \"file_manifest\": {\n    \"SKILL.md\": \"sha256:<file_hash>\"\n  }\n}"
      },
      {
        "title": "Tamper Detection",
        "body": "from schemapin.skill import detect_tampered_files, canonicalize_skill\n\n_, current_manifest = canonicalize_skill(\"./my-skill/\")\ntampered = detect_tampered_files(current_manifest, sig.file_manifest)\n# tampered.modified, tampered.added, tampered.removed"
      },
      {
        "title": "Publishing .well-known Endpoints",
        "body": "Python CLI tools are included:\n\n# Generate a keypair\nschemapin-keygen --output-dir ./keys\n\n# Sign a schema\nschemapin-sign --key ./keys/private.pem --schema schema.json\n\n# Verify a signature\nschemapin-verify --key ./keys/public.pem --schema schema.json --signature sig.b64\n\nGo CLI equivalents are also available (go install github.com/ThirdKeyAi/schemapin/go/cmd/...@v1.3.0)."
      },
      {
        "title": "Architecture",
        "body": "Developer                          Client (AI Platform)\n─────────                          ────────────────────\n1. Generate ECDSA P-256 keypair\n2. Publish public key at           3. Discover public key from\n   /.well-known/schemapin.json        /.well-known/schemapin.json\n4. Sign tool schema                5. Verify signature\n   (canonicalize → SHA-256            (canonicalize → SHA-256\n    → ECDSA sign)                      → ECDSA verify)\n                                   6. TOFU pin the key fingerprint\n                                   7. Check revocation status"
      },
      {
        "title": "Language API Reference",
        "body": "OperationPythonJavaScriptGoRustGenerate keysKeyManager.generate_keypair()KeyManager.generateKeypair()km.GenerateKeypair()generate_key_pair()Sign schemaSignatureManager.sign_schema()SignatureManager.signSchema()sm.SignSchema()sign_data()Verify signatureSignatureManager.verify_signature()SignatureManager.verifySignature()sm.VerifySignature()verify_signature()CanonicalizeSchemaPinCore().canonicalize_schema()new SchemaPinCore().canonicalizeSchema()spc.CanonicalizeSchema()SchemaPinCore::new().canonicalize_schema()Discover keyPublicKeyDiscovery.fetch_well_known()PublicKeyDiscovery.fetchWellKnown()FetchWellKnown()WellKnownResolver (fetch feature)Offline verifyverify_schema_offline()verifySchemaOffline()VerifySchemaOffline()verify_schema_offline()Resolver verifyverify_schema_with_resolver()verifySchemaWithResolver()VerifySchemaWithResolver()verify_schema_with_resolver()Sign skill foldersign_skill()signSkill()skill.SignSkill()sign_skill()Verify skillverify_skill_offline()verifySkillOffline()skill.VerifySkillOffline()verify_skill_offline()Detect tamperingdetect_tampered_files()detectTamperedFiles()skill.DetectTamperedFiles()detect_tampered_files()"
      },
      {
        "title": "Testing",
        "body": "# Python\ncd python && python -m pytest tests/ -v\n\n# JavaScript\ncd javascript && npm test\n\n# Go\ncd go && go test ./...\n\n# Rust\ncd rust && cargo test"
      },
      {
        "title": "Pro Tips for AI Assistants",
        "body": "Always canonicalize before signing or verifying — raw JSON comparison will fail\nUse offline verification when you have pre-fetched discovery data — avoids HTTP calls during schema validation\nTrust bundles are ideal for CI/CD and air-gapped deployments\nChainResolver lets you layer resolvers: bundle → local files → HTTP as fallback\nTOFU pinning means the first key seen for a domain is trusted — warn users on key changes\nAll languages use the same crypto — ECDSA P-256 + SHA-256, so cross-language verification works\nRevocation checking should always be performed — both simple lists and standalone documents\nSkillSigner signs entire directories — ideal for SKILL.md folders uploaded to registries like ClaWHub\n.schemapin.sig is auto-excluded from hashing — you can re-sign a directory without removing the old signature first"
      }
    ],
    "body": "SchemaPin Development Skills Guide\n\nPurpose: This guide helps AI assistants quickly integrate SchemaPin into applications for cryptographic tool schema verification.\n\nFor Full Documentation: See the README, Technical Specification, and language-specific READMEs in each subdirectory.\n\nWhat SchemaPin Does\n\nSchemaPin prevents \"MCP Rug Pull\" attacks by enabling developers to cryptographically sign their tool schemas (ECDSA P-256 + SHA-256) and clients to verify schemas haven't been tampered with. It uses Trust-On-First-Use (TOFU) key pinning and RFC 8615 .well-known endpoints for public key discovery.\n\nPart of the ThirdKey trust stack: SchemaPin (tool integrity) → AgentPin (agent identity) → Symbiont (runtime)\n\nQuick Start by Language\nPython\npip install schemapin\n\nfrom schemapin.crypto import KeyManager, SignatureManager\nfrom schemapin.core import SchemaPinCore\n\n# Generate keys\nprivate_key, public_key = KeyManager.generate_keypair()\n\n# Sign a schema\ncore = SchemaPinCore()\ncanonical = core.canonicalize_schema(schema_dict)\nsignature = SignatureManager.sign_schema(private_key, canonical)\n\n# Verify\nis_valid = SignatureManager.verify_signature(public_key, canonical, signature)\n\nJavaScript\nnpm install schemapin\n\nimport { KeyManager, SignatureManager, SchemaPinCore } from 'schemapin';\n\n// Generate keys\nconst { privateKey, publicKey } = KeyManager.generateKeypair();\n\n// Sign a schema\nconst core = new SchemaPinCore();\nconst canonical = core.canonicalizeSchema(schema);\nconst signature = await SignatureManager.signSchema(privateKey, canonical);\n\n// Verify\nconst isValid = await SignatureManager.verifySignature(publicKey, canonical, signature);\n\nGo\ngo get github.com/ThirdKeyAi/schemapin/go@v1.3.0\n\nimport (\n    \"github.com/ThirdKeyAi/schemapin/go/pkg/core\"\n    \"github.com/ThirdKeyAi/schemapin/go/pkg/crypto\"\n)\n\n// Generate keys\nkm := crypto.NewKeyManager()\nprivKey, pubKey, _ := km.GenerateKeypair()\n\n// Sign a schema\nspc := core.NewSchemaPinCore()\ncanonical, _ := spc.CanonicalizeSchema(schema)\nsig, _ := crypto.NewSignatureManager().SignSchema(privKey, canonical)\n\n// Verify\nvalid, _ := crypto.NewSignatureManager().VerifySignature(pubKey, canonical, sig)\n\nRust\n[dependencies]\nschemapin = \"1.3\"\n\nuse schemapin::crypto::{generate_key_pair, sign_data, verify_signature};\nuse schemapin::core::SchemaPinCore;\n\n// Generate keys\nlet key_pair = generate_key_pair()?;\n\n// Sign\nlet core = SchemaPinCore::new();\nlet canonical = core.canonicalize_schema(&schema)?;\nlet signature = sign_data(&key_pair.private_key_pem, &canonical)?;\n\n// Verify\nlet is_valid = verify_signature(&key_pair.public_key_pem, &canonical, &signature)?;\n\nCore Concepts\n1. Schema Canonicalization\n\nSchemas are canonicalized (deterministic JSON serialization with sorted keys) before hashing. This ensures identical schemas always produce the same hash regardless of key ordering.\n\n2. .well-known Discovery\n\nDevelopers publish their public key at https://example.com/.well-known/schemapin.json:\n\nfrom schemapin.utils import create_well_known_response\n\nresponse = create_well_known_response(\n    public_key_pem=public_key_pem,\n    developer_name=\"Acme Corp\",\n    schema_version=\"1.2\",\n    revocation_endpoint=\"https://example.com/.well-known/schemapin-revocations.json\"\n)\n\n3. TOFU Key Pinning\n\nOn first verification, the developer's public key fingerprint is pinned. Subsequent verifications reject different keys for the same domain — detecting key substitution attacks.\n\n4. Verification Workflows\n\nOnline (standard):\n\nworkflow = SchemaVerificationWorkflow(pin_store)\nresult = workflow.verify_schema(schema, signature, \"https://example.com\")\n\n\nOffline (v1.2.0 — no HTTP required):\n\nfrom schemapin.verification import verify_schema_offline, KeyPinStore\n\npin_store = KeyPinStore()\nresult = verify_schema_offline(\n    schema, signature_b64, domain, tool_id,\n    discovery_data, revocation_doc, pin_store\n)\n\nv1.2.0 Features\nStandalone Revocation Documents\nfrom schemapin.revocation import (\n    build_revocation_document, add_revoked_key,\n    check_revocation, RevocationReason\n)\n\ndoc = build_revocation_document(\"example.com\")\nadd_revoked_key(doc, fingerprint, RevocationReason.KEY_COMPROMISE)\ncheck_revocation(doc, some_fingerprint)  # raises if revoked\n\nTrust Bundles (Offline / Air-Gapped)\n\nPre-package discovery + revocation data for environments without internet:\n\nfrom schemapin.bundle import SchemaPinTrustBundle\n\nbundle = SchemaPinTrustBundle.from_json(bundle_json_str)\ndiscovery = bundle.find_discovery(\"example.com\")\nrevocation = bundle.find_revocation(\"example.com\")\n\nPluggable Discovery Resolvers\nfrom schemapin.resolver import (\n    WellKnownResolver,    # HTTP .well-known lookups\n    LocalFileResolver,    # Local JSON files\n    TrustBundleResolver,  # In-memory trust bundles\n    ChainResolver,        # First-match fallthrough\n)\n\n# Chain: try bundle first, fall back to HTTP\nresolver = ChainResolver([\n    TrustBundleResolver.from_json(bundle_json),\n    WellKnownResolver(timeout=10),\n])\n\nResolver-Based Verification\nfrom schemapin.verification import verify_schema_with_resolver\n\nresult = verify_schema_with_resolver(\n    schema, signature_b64, domain, tool_id,\n    resolver, pin_store\n)\n\nv1.3.0 Features\nSkillSigner — File-Based Skill Folder Signing\n\nSign entire skill directories (e.g., a folder containing SKILL.md) with ECDSA P-256. Produces a .schemapin.sig manifest alongside the files, proving no file has been tampered with.\n\nPython:\n\nfrom schemapin.skill import sign_skill, verify_skill_offline\n\n# Sign a skill directory\nsig = sign_skill(\"./my-skill/\", private_key_pem, \"example.com\")\n# Writes .schemapin.sig into ./my-skill/\n\n# Verify offline\nfrom schemapin.verification import KeyPinStore\nresult = verify_skill_offline(\"./my-skill/\", discovery_data, sig, revocation_doc, KeyPinStore())\n\n\nJavaScript:\n\nimport { signSkill, verifySkillOffline } from 'schemapin/skill';\n\nconst sig = await signSkill('./my-skill/', privateKeyPem, 'example.com');\nconst result = verifySkillOffline('./my-skill/', discoveryData, sig, revDoc, pinStore);\n\n\nGo:\n\nimport \"github.com/ThirdKeyAi/schemapin/go/pkg/skill\"\n\nsig, err := skill.SignSkill(\"./my-skill/\", privateKeyPEM, \"example.com\", \"\", \"\")\nresult := skill.VerifySkillOffline(\"./my-skill/\", disc, sig, rev, pinStore, \"\")\n\n\nRust:\n\nuse schemapin::skill::{sign_skill, verify_skill_offline};\n\nlet sig = sign_skill(\"./my-skill/\", &private_key_pem, \"example.com\", None, None)?;\nlet result = verify_skill_offline(\"./my-skill/\", &disc, Some(&sig), rev.as_ref(), Some(&pin_store), None);\n\n.schemapin.sig Format\n{\n  \"schemapin_version\": \"1.3\",\n  \"skill_name\": \"my-skill\",\n  \"skill_hash\": \"sha256:<root_hash>\",\n  \"signature\": \"<base64_ecdsa_signature>\",\n  \"signed_at\": \"2026-02-14T00:00:00Z\",\n  \"domain\": \"example.com\",\n  \"signer_kid\": \"sha256:<key_fingerprint>\",\n  \"file_manifest\": {\n    \"SKILL.md\": \"sha256:<file_hash>\"\n  }\n}\n\nTamper Detection\nfrom schemapin.skill import detect_tampered_files, canonicalize_skill\n\n_, current_manifest = canonicalize_skill(\"./my-skill/\")\ntampered = detect_tampered_files(current_manifest, sig.file_manifest)\n# tampered.modified, tampered.added, tampered.removed\n\nServer-Side Setup\nPublishing .well-known Endpoints\n\nPython CLI tools are included:\n\n# Generate a keypair\nschemapin-keygen --output-dir ./keys\n\n# Sign a schema\nschemapin-sign --key ./keys/private.pem --schema schema.json\n\n# Verify a signature\nschemapin-verify --key ./keys/public.pem --schema schema.json --signature sig.b64\n\n\nGo CLI equivalents are also available (go install github.com/ThirdKeyAi/schemapin/go/cmd/...@v1.3.0).\n\nArchitecture\nDeveloper                          Client (AI Platform)\n─────────                          ────────────────────\n1. Generate ECDSA P-256 keypair\n2. Publish public key at           3. Discover public key from\n   /.well-known/schemapin.json        /.well-known/schemapin.json\n4. Sign tool schema                5. Verify signature\n   (canonicalize → SHA-256            (canonicalize → SHA-256\n    → ECDSA sign)                      → ECDSA verify)\n                                   6. TOFU pin the key fingerprint\n                                   7. Check revocation status\n\nLanguage API Reference\nOperation\tPython\tJavaScript\tGo\tRust\nGenerate keys\tKeyManager.generate_keypair()\tKeyManager.generateKeypair()\tkm.GenerateKeypair()\tgenerate_key_pair()\nSign schema\tSignatureManager.sign_schema()\tSignatureManager.signSchema()\tsm.SignSchema()\tsign_data()\nVerify signature\tSignatureManager.verify_signature()\tSignatureManager.verifySignature()\tsm.VerifySignature()\tverify_signature()\nCanonicalize\tSchemaPinCore().canonicalize_schema()\tnew SchemaPinCore().canonicalizeSchema()\tspc.CanonicalizeSchema()\tSchemaPinCore::new().canonicalize_schema()\nDiscover key\tPublicKeyDiscovery.fetch_well_known()\tPublicKeyDiscovery.fetchWellKnown()\tFetchWellKnown()\tWellKnownResolver (fetch feature)\nOffline verify\tverify_schema_offline()\tverifySchemaOffline()\tVerifySchemaOffline()\tverify_schema_offline()\nResolver verify\tverify_schema_with_resolver()\tverifySchemaWithResolver()\tVerifySchemaWithResolver()\tverify_schema_with_resolver()\nSign skill folder\tsign_skill()\tsignSkill()\tskill.SignSkill()\tsign_skill()\nVerify skill\tverify_skill_offline()\tverifySkillOffline()\tskill.VerifySkillOffline()\tverify_skill_offline()\nDetect tampering\tdetect_tampered_files()\tdetectTamperedFiles()\tskill.DetectTamperedFiles()\tdetect_tampered_files()\nTesting\n# Python\ncd python && python -m pytest tests/ -v\n\n# JavaScript\ncd javascript && npm test\n\n# Go\ncd go && go test ./...\n\n# Rust\ncd rust && cargo test\n\nPro Tips for AI Assistants\nAlways canonicalize before signing or verifying — raw JSON comparison will fail\nUse offline verification when you have pre-fetched discovery data — avoids HTTP calls during schema validation\nTrust bundles are ideal for CI/CD and air-gapped deployments\nChainResolver lets you layer resolvers: bundle → local files → HTTP as fallback\nTOFU pinning means the first key seen for a domain is trusted — warn users on key changes\nAll languages use the same crypto — ECDSA P-256 + SHA-256, so cross-language verification works\nRevocation checking should always be performed — both simple lists and standalone documents\nSkillSigner signs entire directories — ideal for SKILL.md folders uploaded to registries like ClaWHub\n.schemapin.sig is auto-excluded from hashing — you can re-sign a directory without removing the old signature first"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/jaschadub/schemapin",
    "publisherUrl": "https://clawhub.ai/jaschadub/schemapin",
    "owner": "jaschadub",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/schemapin",
    "downloadUrl": "https://openagent3.xyz/downloads/schemapin",
    "agentUrl": "https://openagent3.xyz/skills/schemapin/agent",
    "manifestUrl": "https://openagent3.xyz/skills/schemapin/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/schemapin/agent.md"
  }
}