Markets

Vendor and marketplace signals

Use this when a community wants portable, anonymous reputation for vendors, marketplace counterparties, or recurring scam patterns.

Use this when a community wants portable, anonymous reputation for vendors, marketplace counterparties, or recurring scam patterns.

Fit

  • Status: supported today.
  • NIP-85 kind: 30382 if the vendor is a Nostr pubkey; 30385 if the subject is an external marketplace identifier.
  • Subject examples: vendor pubkey, vendor:market.example:alice, market:example:item-seller-42.
  • Helpers: aggregateContributions for pubkeys, aggregateIdentifierContributions for external identifiers.
  • Proof version: v2 recommended.
  • Useful metrics: rank, comment_cnt, reaction_cnt.

Subject design

  • Use kind 30382 when the vendor, buyer, escrow agent, or marketplace actor is a Nostr pubkey.
  • Use kind 30385 when the subject is a marketplace account, listing, order pattern, payment handle, or recurring scam identifier.
  • Keep vendor identity, trade fulfilment, dispute behaviour, fraud reports, and marketplace reliability as separate subjects where clients need different actions.
  • Decide whether identifiers are market-local or intentionally portable across markets before publishing them.

What to publish

  • A kind 30382 user assertion or kind 30385 identifier assertion, depending on the subject.
  • A rank profile that says whether the score represents fulfilment reliability, dispute risk, fraud risk, communication quality, or overall counterparty confidence.
  • Proof v2 tags, accepted circle policy, evidence standard, minimum threshold, expiry, recovery, and appeal rules.
  • Separate dispute records, escrow outcomes, refund decisions, or moderator notes when the marketplace needs a complete case history.

Implementation recipe

  1. Decide whether the subject is a Nostr pubkey, a marketplace-specific vendor id, an item listing, or a recurring scam pattern.
  2. Define what rank means: fulfilment reliability, dispute risk, fraud risk, communication quality, or overall counterparty confidence.
  3. Require evidence rules before negative reports, especially if no trade was completed.
  4. Use proof v2 and verify the expected subject, namespace, circle, threshold, and freshness.
  5. Keep dispute resolution, refunds, identity checks, and recovery policy in the marketplace layer.

Worked example

This example uses a private identifier profile. It is intentionally not a global vendor registry.

examples/use-cases/vendor-marketplace-signals.ts
import {
  NIP85_KINDS,
  aggregateIdentifierContributions,
  contributeIdentifierAssertion,
  createTrustCircle,
} from 'nostr-veil'
import {
  defaultMembers,
  externalProfileKind,
  memberIndex,
  proofVersion,
  verifyUseCaseAssertion,
  withCreatedAt,
} from './_shared.js'

const slug = 'vendor-marketplace-signals'
const vendorId = 'vendor:market.example:alice'
const circle = createTrustCircle(defaultMembers.map(member => member.pub))

const contributions = defaultMembers.map((counterparty, index) =>
  contributeIdentifierAssertion(
    circle,
    vendorId,
    externalProfileKind,
    {
      rank: 62 + index * 4,
      reaction_cnt: index + 1,
    },
    counterparty.priv,
    memberIndex(circle, counterparty.pub),
    { proofVersion },
  ),
)

export const assertion = withCreatedAt(aggregateIdentifierContributions(
  circle,
  vendorId,
  externalProfileKind,
  contributions,
  { proofVersion },
))

export const result = verifyUseCaseAssertion(slug, assertion, {
  kind: NIP85_KINDS.IDENTIFIER,
  subject: vendorId,
  subjectTag: 'k',
  subjectTagValue: externalProfileKind,
  circleId: circle.circleId,
  minDistinctSigners: 3,
  freshAfter: assertion.created_at - 300,
})

What to verify

  • Strict syntax and a valid proof v2.
  • The assertion route matches the marketplace subject: p for Nostr pubkeys or k for marketplace identifiers.
  • The counterparty-review circle is trusted for this market and has enough distinct signers for the value at risk.
  • The rank meaning matches the UI action: warning, escrow requirement, search ranking, suspension, or manual review.
  • The assertion is fresh and not superseded by a dispute resolution, recovery assertion, or fraud incident.

What this proves

  • Distinct members of the counterparty circle contributed the trade signal.
  • The final metric tags match the signed anonymous contributions.
  • The signal is portable as a Nostr event.

What not to claim

  • Do not claim the proof adjudicates disputes or proves fraud by itself.
  • Do not claim an external vendor identifier proves real-world identity unless the marketplace separately verified it.
  • Do not claim old negative scores should last forever. Reputation needs expiry, recovery, and re-review policy.

Failure handling

  • Reject assertions with weak evidence, unknown circles, wrong subject routes, stale scores, or unclear metric direction.
  • Send high-value or contested cases to dispute review before applying automatic marketplace penalties.
  • Publish recovery, refund, or correction assertions when a case is resolved or an account is restored.
  • Keep market-local identifiers local unless cross-market linking is a stated safety feature.

Operational requirements

Risk to handleRequired control
The proof does not adjudicate disputes.Add evidence submission, dispute review, appeal paths, refund policy, and moderator escalation.
The proof does not prove vendor identity outside the chosen profile.Use Nostr pubkeys, marketplace account checks, NIP-05/domain checks, escrow records, or other identity controls as appropriate.
Colluding circle members can still coordinate.Use circle admission policy, independent circles, federation thresholds, and anomaly review for high-value markets.
Old negative scores can become stale.Define expiry, recovery, pardon, or re-review rules so reputation can change when behaviour changes.

Policy choices

  • Are negative reports allowed without a completed trade?
  • How are refunds, delivery failures, and fraud weighted?
  • How does a vendor recover from old bad scores?
  • Should marketplace-specific identifiers be linkable across markets?

NIP-85 kind reference

NIP-85 defines the assertion kind by the subject being scored. The kind number is part of the proof v2 context, so deployments should verify both the number and the subject hint tag.

30382 User assertion

Nostr pubkey subjects. Subject hint: p.

30383 Event assertion

Nostr event id subjects. Subject hint: e.

30384 Addressable event assertion

NIP-33 address subjects. Subject hint: a.

30385 NIP-73/external identifier assertion

packages, relays, domains, vendors, and other identifiers. Subject hint: k.

10040 Trusted service provider declaration

provider metadata, not a score assertion. Subject hint: provider tags.

Spec: NIP-85 trusted assertions.

Live relay test

The opt-in relay test signs this canonical example as real Nostr event data, publishes it to wss://relay.trotters.cc, fetches it back by id, and re-runs the application, syntax, Nostr signature, canonical tag, and proof checks.

Passed 2026-05-17T21:54:12.000Z
Events
1/1 fetched from relay
Proof
3/3 threshold from a 3-member ring
Run
tf7bic-3b3a5ae6d6
  • Canonical example passes locally
  • Relay stored and returned every signed event
  • Fetched Nostr event signatures are valid
  • Fetched tags match the canonical example
  • NIP-85 syntax validation passes
  • nostr-veil proof verification passes
  • Deployment profile verifier passes
7725085e4982...0fc44d8e

Run the same check with npm run test:use-cases:relay -- --write docs/use-case-relay-checks.json.

Safety checks

Each canonical use-case example is also exercised by an adversarial test harness. These are the failure modes a production verifier should reject before acting on the score.

Tampered metric

Published scores must still match the signed contribution aggregate.

Wrong subject

The d tag and subject hint must stay bound to the signed v2 proof.

Wrong kind

The assertion kind must match the profile and the signed v2 context.

Proof downgrade

New deployment profiles require proof v2.

Duplicate signer

Repeated key images must not increase the signer count.

Insufficient threshold

Removing a signature must fail the profile threshold.

Stale assertion

created_at must remain inside the freshness window.

Unknown circle

The circle ID must be accepted by deployment policy.

Unsigned policy

verifyProductionDeployment() should require a signed deployment bundle from a trusted publisher.

Relay mutation

Fetched event content and tags must match the Nostr signature.

Use validateUseCaseProfileDefinition() for custom profiles, then verifyProductionDeployment() with trusted bundle publishers, signed relay events, accepted circle manifests, expected subject, freshness, and threshold policy so these checks are not left to application glue. For application UI and audit logs, use verifyProductionDeploymentReport() or createProductionDecisionReport() so failures include issue codes, remediation text, a recommended action, pass/fail/not-checked status for the controls, and the profile's proofClaims, proofLimitations, requiredControls, and recommendedActions.

Next examples