/ · trust · signing-policy

How we sign Suite documents and Pulse receipts

The 11 Suite JSON documents and AI Procurement Pulse receipts have a published signing method. This page explains how to verify them against a trusted key and where the manual GitHub root-upload workflow checks their signatures. Other artifacts, including the dated apex attestation, have separate verification paths. A dry-run on 2026-06-01 exposed signature drift and prompted this documentation.

The keypair

The 11 Suite JSON documents listed below and AI Procurement Pulse receipts use one ed25519 keypair. Its public key is published at a stable URL. The dated apex attestation uses a different key at /.well-known/kg-pubkey.json. Other /.well-known/ resources are outside this Suite/Pulse signing claim. To authenticate a publisher, verify with a key you trust independently of the document being checked.

Algorithm
ed25519 (RFC 8032)
Public key URL
https://kineticgain.com/.well-known/pulse-signing.json
Public key (base64 SPKI-DER)
MCowBQYDK2VwAyEARxsDtZsl4R481NdBerN2RlCF74VZdQhqRHpgvAIJoTo=
Published
2026-05-28
Private key
Not published. The documented manual procedure supplies a PKCS#8 PEM key to scripts/sign-suite-docs.mjs in the procurement-pulse-engine repo. This public page cannot independently prove private-key custody or handling.
Rotation policy
Annual or on compromise. New keypair published at the same URL with a signing_key_version bump; old verifiable signatures remain valid against the old key (kept in archive). Compromise → revocation note at the same URL within 24 hours.

What we sign

The 11 KG Suite JSON documents listed here each carry a top-level signature block that verifies against the Suite/Pulse public key above.

PathWhat it declares
/.well-known/aeo.jsonAEO entity card, Kinetic Gain's answer-engine identity
/.well-known/agents/index.jsonAgent cards we publish
/.well-known/prompts/index.jsonPrompt provenance index
/.well-known/evidence/index.jsonAI evidence bundles index
/.well-known/tool-cards/index.jsonMCP tool cards
/.well-known/tutor-cards/index.jsonAI tutor cards
/.well-known/student-ai/index.jsonStudent AI disclosure
/.well-known/aup.jsonClassroom AI acceptable-use policy
/.well-known/clinical-ai/index.jsonClinical AI disclosure
/.well-known/incidents/index.jsonAI incident cards
/.well-known/decisions/index.jsonAI procurement decision cards

The same key signs the /.well-known/pulse-receipt.json attestation that publishes the locked AI Procurement Pulse baseline.

Verification procedure

To verify a listed Suite document, fetch it, separate the signature block, canonicalize the rest, and ed25519-verify against a trusted copy of the Suite/Pulse public key. These examples show the process:

1. Node.js (built-in, zero deps)

// signature.mjs lives in procurement-pulse-engine; vendor-able into your project.
import { verifyDocument } from "./signature.mjs";

const doc = await (await fetch("https://kineticgain.com/.well-known/aeo.json")).json();
const trustedKey = "MCowBQYDK2VwAyEARxsDtZsl4R481NdBerN2RlCF74VZdQhqRHpgvAIJoTo=";
if (doc.signature?.public_key !== trustedKey) throw new Error("Unexpected signing key");
const result = await verifyDocument(doc);
if (result.status !== "verified") throw new Error("Invalid signature");
console.log(result);  // { status: "verified", keySource: "embedded" }

2. Python (cryptography lib)

import json, requests
from base64 import b64decode
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
from cryptography.hazmat.primitives.serialization import load_der_public_key

def canonical(v):
    if isinstance(v, list): return "[" + ",".join(canonical(x) for x in v) + "]"
    if isinstance(v, dict):
        return "{" + ",".join(json.dumps(k, ensure_ascii=False) + ":" + canonical(v[k])
                              for k in sorted(v.keys())) + "}"
    return json.dumps(v, ensure_ascii=False)

doc = requests.get("https://kineticgain.com/.well-known/aeo.json").json()
sig = doc.pop("signature")
trusted_key = "MCowBQYDK2VwAyEARxsDtZsl4R481NdBerN2RlCF74VZdQhqRHpgvAIJoTo="
if sig["public_key"] != trusted_key: raise ValueError("Unexpected signing key")
pk = load_der_public_key(b64decode(trusted_key))
pk.verify(b64decode(sig["value"]), canonical(doc).encode())   # raises on failure
print("verified")

3. Shell (openssl)

curl -s https://kineticgain.com/.well-known/aeo.json > doc.json
# (separate body + signature with jq, base64-decode pubkey + value, openssl pkeyutl -verify)
# This is an outline, not a runnable verifier; pin the trusted public key.

A signature that verifies only against a key embedded in the same downloaded document shows internal consistency, not publisher identity. Pin the expected key through a separately trusted channel. A valid signature also does not establish when a document was published or whether it describes the current deployment.

The canonicalization is JCS-style with one important detail: do not escape non-ASCII. Python's json.dumps defaults to ensure_ascii=True and would produce different bytes than Node's JSON.stringify. We caught this bug ourselves on 2026-06-01. See the incident below.

Manual root-upload signature check

When .github/workflows/deploy.yml is manually dispatched for a root upload, its Python step verifies the 11 Suite document signatures before uploading. An unsigned document, invalid signature, or canonical-form mismatch stops that workflow's upload and reports the failed document. If a document changed legitimately, re-sign it with the authorized Suite key before retrying:

node scripts/sign-suite-docs.mjs --apex . --key /path/to/kg-pulse-signing-key.pem

This check covers only that manual root-upload workflow. A Git push, a verify-only dispatch, or a local SFTP upload does not automatically run it. Those release paths need an explicit Suite signature check before publication. The workflow compares the published Suite/Pulse key against a reviewed SHA-256 fingerprint, rejects a mismatched embedded key or signing-key URL, and verifies the 11 signatures over canonical JSON. Its successful run applies to the documents in that run, not future deployments or the local SFTP path.

The 2026-06-01 incident, why this page exists

Caught by dry-run, fixed before publication

On 2026-06-01 we dry-ran the AI Procurement Pulse Issue #5 workflow, then scheduled for Aug 15, 2026. The dry-run reported 0/11 verified Suite documents, against the locked baseline's 11/11 verified. Issue #5 has not been published.

Root cause: between the original signing on 2026-05-28 and the dry-run on 2026-06-01, one or more documents had been edited (content updates, spec bumps) without re-signing. Ed25519 verification correctly failed, and would have failed publicly when the August cron published the issue.

Fixes shipped same day:

  1. Wrote a reusable batch signer at procurement-pulse-engine/scripts/sign-suite-docs.mjs.
  2. Re-signed all 11 documents in-place; verified each roundtrip before writing.
  3. Re-ran the dry-run → 11/11 verified.
  4. Added the manual root-upload verify step described above to catch drift on that workflow path.

We're publishing this because honesty about the failure mode is part of the methodology. If we'd noticed in August instead of June we'd have published "0/11 verified" in the very issue that talks about how few vendors sign their docs. The dry-run and manual workflow gate provide checks when they are run; each other release path needs its own verification.

Discipline going forward

The workflow we ourselves follow, in order:

  1. Edit a Suite document in kineticgain-com-apex/.well-known/.
  2. Re-run node scripts/sign-suite-docs.mjs --apex /path/to/apex --key /path/to/private-key.pem in the procurement-pulse-engine repo.
  3. Commit the re-signed document to apex.
  4. Before publication, verify all 11 signatures against the trusted Suite/Pulse key. The manual root-upload workflow performs that pinned-key check; a local SFTP upload needs its own explicit check.
  5. When the quarterly AI Procurement Pulse job runs, its drift report can catch changes missed by the deploy-time check.

Signing and verification are release practices. A push by itself does not invoke the manual deployment workflow, and the local SFTP path does not inherit its signature gate. A published quarterly drift report provides an additional check when a Pulse issue is released.

Coordinated disclosure

If you find a way to forge a signature, demonstrate two distinct documents that hash to the same canonical form, or otherwise break the verification chain, report it privately to miz@kineticgain.com. We review the report and coordinate remediation and disclosure timing based on the issue. Credit is offered with the reporter's consent.

Read the disclosure policy for reporting and scope. The apex /.well-known/security.txt provides the RFC 9116 contact for the apex and our published products.

Reference scaffolding for cryptographic methodology disclosure, not a SOC 2 / ISO 27001 / NIST AI RMF / EU AI Act certified or compliant attestation. Compliance posture depends on your organization's full control environment and external attestation specific to each regulatory regime.