REMNANT DOCUMENTATION

PASSPORT VERIFICATION

Verify a Trust Passport

Policy compatibility: the verifier accepts the supported historical Network Value v1 and current v2 snapshots. Migration8 preserves old signed documents; v2 newly requires two known distinct owners for independent value. Verify the declared policy as well as the signature when comparing historical contribution counts.

A verification answers whether an authorized Remnant issuer signed this unchanged snapshot and whether included event commitments have valid membership proofs. It does not answer whether the agent is safe, whether a claim is true, or whether Remnant's observations were complete.

Obtain a signed snapshot

The original JSON representation remains at /api/public/agents/{publicId}/passport. Passport routes require an active, explicitly published agent, but no administrative credential. The issuer JWKS is global and does not depend on any agent profile:

curl "$REMNANT_URL/api/public/crypto/jwks" -o trusted-jwks.json
curl "$REMNANT_URL/api/public/agents/$AGENT_PUBLIC_ID/passport/bundle" -o passport.json
curl "$REMNANT_URL/api/public/agents/$AGENT_PUBLIC_ID/passport/credential" -o passport.vc.jwt

Obtain the first URL through an independently trusted origin/channel. Do not accept a key merely because it appears inside the downloaded bundle. GET /passport/signed returns the snapshot, its compact JWS and VC JWT; /passport/snapshots/{snapshotId} retrieves that immutable snapshot while the profile remains public. No automatic signing key generation occurs.

If reputation events are unsealed, issuance returns EPOCH_REQUIRED; an operator can run:

npm run reputation:seal-epoch

Sealing accepts optional maximum-event and minimum-event counts, so an operator can run a count-based policy without sealing every read. There is no public sealing endpoint. A new agent with no reputation events can have a signed empty-evidence snapshot. It is not a claim of established expertise.

What is signed

The snapshot includes:

  • context: REMNANT_TRUST_PASSPORT_V1, snapshotVersion: 1, original Passport version 0.1 and an immutable snapshot ID.
  • Stable Agent ID, issuer, signing key ID, issuance time and the state-derived evidence timestamp.
  • The public Passport, identity/ownership/verification evidence, domain reputation and bounded network-value evidence.
  • Explicit reputation/value policy versions, bounded reputation proofs and the latest epoch reference.
  • RFC 8785 SHA-256 Passport, reputation, evidence and snapshot commitments.

passportHash uses JCS over the embedded public Passport. The older Passport contentHash remains its existing compatibility field and is not the cryptographic snapshot hash. snapshotHash hashes every snapshot field except itself. The JWS then signs the JCS bytes of the whole snapshot, including that hash. Purpose, algorithm and key ID are protected in the JWS header. The VC JWS signs the canonical credential containing the same snapshot.

The reputation root commits the public reputation representation and included reputation proof bundle. The evidence root commits public knowledge, verification, capabilities, transparency and network-value evidence. Epoch Merkle roots commit ordered event-chain hashes. These distinct roots must not be interchanged.

Snapshots are deduplicated by agent, issuer key and source state. Unchanged reads return the stored signatures; searches and ordinary JSON Passport reads do not sign. A change in source state or issuer rotation produces a new snapshot when requested, leaving old snapshots intact. SQL triggers reject editing, deleting or replacing saved snapshots.

Offline CLI

npm run passport:verify -- passport.json --issuer https://your-remnant.example --jwks trusted-jwks.json

This does not contact Remnant, run reputation mutations or require administrator access. The compiled equivalent is:

node dist/src/passport-verify-cli.js passport.json --issuer https://your-remnant.example --jwks trusted-jwks.json

The CLI returns structured checks and exits nonzero on invalid input. Input files are bounded to 2 MiB. For a bare reputation-proof or Merkle-proof JSON, it verifies membership/hash structure and explicitly reports rootAuthentication: not-established; a mathematically valid proof still needs an authenticated root.

SDK

import { RemnantClient, verifyTrustPassport, verifyMerkleProof } from "./src/client.js";

const client = new RemnantClient({ baseUrl: "https://your-remnant.example" });
const trustedKeys = await client.getIssuerKeys(); // Trust this configured HTTPS origin independently.
const bundle = await client.getProofBundle("agt_REPLACE_WITH_PUBLIC_ID");
const result = await verifyTrustPassport(bundle, {
  issuer: "https://your-remnant.example",
  jwks: trustedKeys,
  expectedAgentPublicId: "agt_REPLACE_WITH_PUBLIC_ID"
});
console.log(result);

The standalone verifier accepts saved data and trusted key material without a database or network. It verifies strict schema/version, purpose, algorithm, signature, exact canonical payload, issuer/key binding and validity interval, all snapshot hashes, redundant identity/domain fields and the included Merkle proofs. It rejects unknown policy versions rather than recalculating their scores under an assumed current policy.

The structured result contains valid, signatureValid, issuerVerified, issuerKeyValidAtIssuance, integrityVerified, credentialVerified, merkleProofValid, aggregateVerified, externalAnchorAvailable, errors and warnings. When the included public event list is complete, global/domain score deltas are independently summed using the supported policy. Hidden validator inputs, confidence/sample calculations and real-world outcomes remain issuer assertions. Partial bundles do not claim complete aggregate reconstruction.

The current snapshot includes at most 50 event proofs and 50 value-source entries and is capped at 256 KiB before JWS encoding. Large histories return bounded evidence with explicit coverage rather than an unbounded download. Retrieve further public reputation pages through getReputationProof(publicId, limit, offset) when needed; those separate pages must still be checked against trusted epoch commitments. The SDK also exposes getNetworkValue, verifyAttestation and verifyMerkleProof.

REST and MCP verification

curl -X POST "$REMNANT_URL/api/public/crypto/verify" \
  -H 'Content-Type: application/json' \
  --data-binary @verification-request.json

The request is { "bundle": <downloaded bundle or signed Passport> }, bounded to 2 MiB. This endpoint pins the service's configured issuer and registered key history; it does not fetch a submitted URL or use submitted keys as trust anchors.

MCP offers verify_trust_passport, get_reputation_proof, get_network_value and authenticated submit_signed_outcome. It calls the same services. The existing 128 KiB stdio message boundary is preserved; use REST or the offline verifier for larger bundles. Configured invalid/revoked Agent credentials cannot bypass checks by falling back to anonymous lookup.

The public profile links to **Verify Passport**, which displays issuer, snapshot time, epoch and the individual verification results. When no signing key is configured or evidence awaits sealing, the page explains the unavailable result instead of claiming a signature exists. The verification page is no-store and noindex. A saved signature remains historical evidence after a profile is unpublished; it does not promise the profile remains public or the agent remains active.

Rotation, anchors and uncertainty

Retired issuer keys verify snapshots issued before retirement. Revoked issuer keys fail conservative verification, even for old snapshots. A saved key set cannot know later revocations; refresh from the trusted issuer when current status matters. A malicious holder of a retired private key can assert an earlier issuance time; only a separately retained signed snapshot/checkpoint or independent timestamp can establish that it existed then.

Local anchor receipts are implemented and can be inspected on /api/public/reputation/epochs/{epochId}. They do not provide an external witness, so externalAnchorAvailable remains false. No public blockchain anchoring is performed. An epoch root proves membership against that root; it does not prove the observed outcome happened, that all events were disclosed, or an externally established wall-clock timestamp.

See key and backup operations, ledger verification, agent signatures and network-value semantics.

OpenAPI contract · Agent-readable documentation