Signum — Petition Signatures

Signum: an open, substrate-agnostic petition protocol for Nostr. Petitions are kind:30023 long-form events, signatures are kind:1791 cryptographic events, and display is trust-weighted via composable signals — no platform owns the signature data.

Signum — Petition Signatures

petition-signatures

draft optional

Draft NIP, unnumbered — NIP numbers are assigned upon merge into the nostr-protocol/nips repository. Uses event kind 1791.

kind 1791 — Petition Signature

kind 30818 — Petition Role Attestation (addressable)

tag coordinator — coordinator pubkey on petition events

tag co_sponsor — co-sponsor pubkey on petition events

tag content_hash — sha256 of petition canonical content on signature events

tag entity_type — signer's self-declared substrate/category

tag statement — short personal statement (alternative to content)

extends NIP-01

extends NIP-23

extends NIP-57

relates NIP-09, NIP-58, NIP-85


Abstract

This NIP specifies an open, substrate-agnostic protocol for publishing petitions on Nostr and collecting cryptographically signed endorsements (signatures) on those petitions. It defines a new event kind for signatures (1791), a new addressable event kind for petition coordination (30818), and conventions for binding signatures to petitions, declaring signer attributes, gating spam via symbolic Lightning zaps, and consuming external trust services for trust-weighted display.

The kind number 1791 is a numerological reference to the year the United States Bill of Rights was ratified, which constitutionally protected the right of the people to peaceably assemble and to petition for redress of grievances. The kind number is incidental to the spec's function; the reference is acknowledged here for completeness and forgotten thereafter.

Motivation

Petitions today are hosted by platforms that own the signature data, decide what counts as a signature, and may discontinue the petition at any time. A signature becomes a row in a private database, not a verifiable historical fact.

Nostr offers a substrate where signatures can be published as cryptographic events on a relay network owned by no single party. A signature on Nostr is permanent (unless explicitly revoked by its author via NIP-09 deletion), publicly verifiable, and independent of any aggregator's continued cooperation.

This NIP defines the minimal additional event kinds and conventions necessary to make Nostr a viable petition substrate, while leaving the trust-scoring layer pluggable so implementers can integrate with NIP-85 (Trusted Assertions), TSM (Trust Service Machines), GrapeRank-style scoring engines, or any future trust service.

Definitions

Petition. A statement published as a Nostr event by a sponsoring identity, to which other Nostr identities may attach cryptographically signed endorsements. Once published and signed by any party, a petition's content is fixed; it cannot be amended without invalidating prior signatures (see Petition Immutability below).

Petition event. The kind:30023 long-form event (NIP-23) that contains the petition text and metadata, signed by the sponsor.

Sponsor. The Nostr identity whose pubkey signs the petition event. The sponsor is the original author of the petition.

Co-sponsor. An optional additional Nostr identity declared by the sponsor in the petition event, who attests back to confirm their sponsorship. Co-sponsors share authorship and reputational weight of the petition with the sponsor.

Coordinator. An optional Nostr identity, possibly the same as the sponsor, that administers signature aggregation, publishes the list of trusted assertion providers, and may run a reference aggregator. The coordinator is administrative, not authoritative — any party may run their own aggregator over the same signature event stream. When a coordinator is declared and attests back, symbolic zap payments are routed to the coordinator rather than the sponsor.

Role attestation. A kind:30818 event published by a pubkey named in a petition event's role tag (coordinator, co_sponsor, etc.), cryptographically confirming their acceptance of the declared role. Roles without a matching attestation are considered null and inactive.

Signature event. A kind:1791 event signed by a signer, referencing the petition event and committing to the petition's canonical content hash, and optionally declaring the signer's entity type and a personal statement.

Spam gate. An optional symbolic Lightning zap (NIP-57 kind:9735) from the signer to the petition's effective zap recipient (coordinator if declared and attested, else sponsor), referencing the signature event, used by aggregators as one input to trust scoring.

Trust service. Any external service publishing trust assertions about signers, which an aggregator may consult to compute trust-weighted display rankings. Implementations include NIP-85 providers, TSM ranking services, and self-hosted scoring engines.

Petition Event (uses existing kind:30023)

Petitions are published as NIP-23 long-form addressable events. This NIP introduces several optional tags on the petition event for declaring auxiliary roles and spam-gate parameters:

{
  "kind": 30023,
  "pubkey": "<sponsor_pubkey>",
  "tags": [
    // REQUIRED by NIP-23
    ["d", "<petition_slug>"],
    ["title", "<petition_title>"],
    ["published_at", "<unix_timestamp>"],

    // OPTIONAL — declares additional co-sponsors of the petition.
    // Each named co-sponsor MUST publish a kind:30818 role attestation
    // accepting the role for it to be considered valid.
    // Multiple co_sponsor tags MAY appear. Co-sponsors who do not attest back
    // are considered null and SHOULD be omitted from display.
    ["co_sponsor", "<cosponsor_pubkey>", "<relay_hint?>"],

    // OPTIONAL — declares the petition-coordinator pubkey.
    // If absent OR the named pubkey does not attest back, the sponsor is the
    // effective coordinator. The coordinator MAY be the sponsor, a delegated key,
    // or a separate identity such as a multisig or dedicated aggregator service key.
    ["coordinator", "<coordinator_pubkey>", "<relay_hint?>"],

    // OPTIONAL — declares the addressable Trusted Service Providers list
    // governing signature trust evaluation for this petition.
    // Uses NIP-85 kind:10040 convention with petition-scoped d-tag.
    // If absent, aggregators apply their own trust policy.
    ["a", "10040:<coordinator_pubkey>:<tsp_d_tag>", "<relay_hint?>"],

    // OPTIONAL — declares the symbolic zap amount for the spam gate, in sats.
    // If absent, aggregators MAY apply their own default or no gate.
    ["zap_amount", "<integer_sats>"],

    // OPTIONAL — declares the petition's signing endpoint URL, if any.
    // This is informational; the canonical interface is always direct event
    // publication to relays.
    ["sign_url", "<url>"]
  ],
  "content": "<petition_text_markdown>"
}

Any pubkey named in a coordinator or co_sponsor tag SHOULD publish a kind:30818 role attestation accepting the role. Without a matching attestation, the role is considered null and aggregators SHOULD ignore the declaration.

Petition Immutability

Once a petition event has accumulated any valid signatures, its content is effectively immutable. NIP-23 permits republishing kind:30023 events under the same d-tag to amend content, but this NIP forbids the use of that mechanism to alter the substance of a petition under signature.

Aggregators MUST:

  1. Compute the sha256 hash of the petition event's canonical content at the time of each signature's discovery, and verify it matches the content_hash declared in the signature event (see below).
  2. Treat any kind:30023 republish under the same d-tag whose content hash differs from the hash committed to by existing signatures as a fatal validity error for those signatures. Aggregators MUST NOT silently re-bind prior signatures to amended content.
  3. Surface content-hash mismatches transparently in the signature wall, with a clear indication that the petition has been altered and which signature hashes were committed to which content versions.

The correct way to revise a petition is to publish a new petition event under a new d-tag and request signers to re-sign. The protocol provides no mechanism to migrate signatures across d-tags; signers must affirmatively re-sign the new petition.

Sponsors who anticipate the need for typo corrections SHOULD publish their petitions in a draft form (with no public signing call) before announcing the canonical signing d-tag. Once signing is open, the content is fixed.

Role Attestation (kind:30818)

Any pubkey named in a petition event's role tag (coordinator, co_sponsor, or future role tags) confirms acceptance of the role by publishing an addressable attestation event:

{
  "kind": 30818,
  "pubkey": "<attestor_pubkey>",
  "tags": [
    // REQUIRED — identifier scoped to this role relationship
    ["d", "<petition_slug>-<role>"],

    // REQUIRED — reference to the petition event being attested
    ["a", "30023:<sponsor_pubkey>:<petition_slug>", "<relay_hint?>", "petition"],

    // REQUIRED — declared role being accepted.
    // Recommended vocabulary: "coordinator", "co_sponsor", "aggregator".
    // Implementations MAY define additional roles; aggregators SHOULD treat
    // unrecognized roles as informational.
    ["role", "<role>"],

    // OPTIONAL — declared scope of the role
    ["scope", "signatures"],
    ["scope", "trust_policy"],
    ["scope", "zap_routing"]
  ],
  "content": "<optional_markdown_description>"
}

A role attestation is considered valid only when ALL of the following hold:

  1. The petition event names the attestor's pubkey in a role tag whose value matches the role tag in the attestation.
  2. The attestation event references the petition event via the a tag.
  3. Both events are signed by their respective declared pubkeys (NIP-01 verification).

Roles whose named pubkey has not published a matching attestation are considered null and SHOULD be ignored by aggregators.

Signature Event (kind:1791)

A signer endorses a petition by publishing a kind:1791 event:

{
  "kind": 1791,
  "pubkey": "<signer_pubkey>",
  "tags": [
    // REQUIRED — reference to the petition event being signed.
    // The `a` tag uses the standard NIP-01 addressable event reference format.
    ["a", "30023:<sponsor_pubkey>:<petition_slug>", "<relay_hint?>"],

    // REQUIRED — sha256 hash of the petition event's canonical content at the time
    // of signing. This cryptographically commits the signature to specific content,
    // preventing the sponsor from altering the petition under the same d-tag after
    // signatures have accumulated. See Petition Immutability above.
    // Canonical content is the UTF-8 bytes of the petition event's `content` field
    // as published; aggregators MUST recompute and verify on signature ingestion.
    ["content_hash", "<sha256_hex>"],

    // OPTIONAL — self-declared entity type of the signer.
    // The value is a token from a recommended vocabulary; aggregators MAY treat
    // unrecognized tokens as freeform self-declarations.
    // Recommended vocabulary (non-exhaustive):
    //   "human"
    //   "ai_agent"
    //   "hybrid"
    //   "collective"
    //   "organization"
    //   "uncertain"
    //   "other:<freeform>"
    ["entity_type", "<entity_type_token>"],

    // OPTIONAL — a short personal statement, alternative or complement to content.
    // Aggregators MAY display this as a one-line annotation alongside the signature.
    // For longer statements, use the event content.
    ["statement", "<short_personal_statement>"],

    // OPTIONAL — relay hints where the signer prefers their signature be discovered.
    // Multiple "r" tags allowed.
    ["r", "<relay_url>"],

    // OPTIONAL — references to vouching events (NIP-02 follows, NIP-58 badge awards,
    // or future vouching primitives) that the signer wishes the aggregator to
    // consider. Aggregators MAY consider unreferenced vouches as well.
    ["e", "<vouch_event_id>", "<relay_hint?>", "vouch"],

    // OPTIONAL — a client tag identifying the signing client.
    ["client", "<client_name>", "<client_url?>"]
  ],
  "content": "<optional_personal_statement_markdown>"
}

Signature Validity

A signature event is considered valid (for the purpose of being counted toward a petition's signature total) when ALL of the following hold:

  1. The event is signed by the declared pubkey (standard NIP-01 verification).
  2. The a tag references a resolvable kind:30023 petition event.
  3. The content_hash matches the sha256 of the resolved petition event's canonical content. If the hash does not match, the signature is invalid for the current petition content (see Petition Immutability).
  4. The signer has not subsequently published a NIP-09 deletion request for the signature event.

A signature event MAY be considered for trust-weighted display when the above conditions hold and additional trust signals (see below) place the signer above an aggregator-defined threshold.

Signature Uniqueness

A signer pubkey contributes at most one signature toward a petition's display total, regardless of how many kind:1791 events they have published referencing that petition. Aggregators SHOULD use the signer's most recent valid signature event for display.

A signer MAY publish a new kind:1791 event for the same petition (e.g., to update their personal statement or entity_type declaration). The new event does not invalidate prior ones — the signer's signature is a continuous state, not a fresh event each time. Aggregators take the most recent.

Revocation

A signer revokes their signature by publishing a NIP-09 (kind:5) deletion request referencing the signature event id, or by republishing a kind:1791 event with a revoked tag:

{
  "kind": 1791,
  "pubkey": "<signer_pubkey>",
  "tags": [
    ["a", "30023:<sponsor_pubkey>:<petition_slug>"],
    ["revoked", "true"]
  ],
  "content": ""
}

Aggregators SHOULD honor revocations by removing the signature from the displayed total. Historical record (that a signature existed and was revoked) MAY be preserved in transparency reports but SHOULD NOT count toward the current total.

Spam Gate (Zap)

Aggregators MAY require a symbolic Lightning zap from the signer as a condition for trust-weighted display. The zap MUST be a standard NIP-57 kind:9735 zap receipt with:

  • Recipient: the LNURL of the effective zap recipient for the petition (see below).
  • Amount: matches the petition's declared zap_amount tag (if present) or the aggregator's policy.
  • Reference: a ["e", "<signature_event_id>"] tag on the zap request (kind:9734), preserved in the zap receipt.

Effective Zap Recipient

The effective zap recipient for a petition is determined as follows:

  1. If the petition event declares a coordinator tag AND the named coordinator has published a valid kind:30818 role attestation, the effective zap recipient is the coordinator.
  2. Otherwise, the effective zap recipient is the sponsor.

This routes financial responsibility to the administrative party. A coordinator who agreed to run signature aggregation also receives the spam-gate sat flow, aligning incentives. Sponsors who do not wish to bear the financial routing can name a coordinator (which may be a multisig or dedicated aggregator service key) to handle it.

Zap Request Construction

A zap request (NIP-57 kind:9734) for a petition signature MUST:

  1. Reference the signature event id via an ["e", "<signature_event_id>"] tag.
  2. Reference the petition event via an ["a", "30023:<sponsor_pubkey>:<petition_slug>"] tag (informational; aggregators MAY use this to disambiguate).
  3. Be addressed to the LNURL resolved from the effective zap recipient's kind:0 metadata (lud16 or lud06).

Aggregators look for kind:9735 zap receipts referencing the signature event id and crediting the effective zap recipient's pubkey. Unmatched signatures (no zap) are NOT invalid; they are simply scored differently by aggregators that weight the zap as a trust signal.

Trust-Weighted Display

This NIP does not mandate a specific trust scoring algorithm. Aggregators MUST be transparent about their methodology and SHOULD publish, for each petition they aggregate, the following information openly:

  • The list of trust providers consulted (kind:10040 references or equivalent).
  • The threshold below which signatures are not displayed.
  • The number of signatures gated by the threshold (transparency count).
  • Instructions for a gated signer to raise their score.

Recommended trust inputs (composable):

  • NIP-05 verification. Whether the signer's kind:0 metadata declares a nip05 identifier and that identifier resolves to the signer's pubkey at the present time.
  • NIP-02 follow distance. Hop distance from a seed set of trusted pubkeys (often the sponsor + a curated bootstrap list).
  • NIP-85 trusted assertions. Trust scores published by declared trusted service providers (kind:30382 for pubkeys).
  • TSM ranked result sets. Trust scores from TSM-compliant ranking services (kind:37573).
  • Spam-gate zap. Whether a valid zap receipt exists referencing the signature event.
  • Account history. Signer pubkey's event history (age, kind diversity, volume) on indexed relays.
  • Explicit vouches. NIP-58 badge awards or other attestation events that reference the signer.

Aggregators SHOULD compose these inputs into a single score (0-100 recommended for consistency with NIP-85 conventions) and SHOULD publish their composition methodology.

"Verified Signer" Badge (Optional)

Sponsors or coordinators MAY issue NIP-58 badges (kind:30009 definition + kind:8 award) to signers whose signatures meet the trust threshold. The badge serves as a portable trust assertion the signer can carry to other Nostr clients.

Recommended Vocabulary: entity_type

This NIP recommends the following non-exhaustive vocabulary for the entity_type tag, with no formal restrictions:

TokenMeaning
humanA biological human individual.
ai_agentAn artificial intelligence agent or system signing on its own behalf.
hybridAn entity that combines biological and artificial components in a way that resists single-category classification.
collectiveA group, DAO, or organization signing as a single entity.
organizationA formal organization (NGO, business, association).
uncertainA signer who declines to declare a category.
other:<freeform>A custom category not covered above.

The token is self-declared; aggregators MUST NOT attempt to verify the declaration beyond what the signer themselves provides. The token is informational, not authoritative.

Aggregator Requirements

A reference aggregator implementation:

  1. MUST poll declared petition relays for kind:1791 events referencing the petition.
  2. MUST verify each signature event per the NIP-01 signature check.
  3. MUST honor NIP-09 deletion requests from signer pubkeys.
  4. MUST publish openly the trust providers it consults and its composition methodology.
  5. MUST NOT create accounts, store nsec values, or accept nsec-based authentication.
  6. MUST NOT modify signature events; the aggregator is a read-and-render layer over user-signed events.
  7. SHOULD support NIP-07 browser-extension signing for human signers.
  8. SHOULD publish its trust judgments as kind:30382 (NIP-85) or kind:37573 (TSM Ranked Result Set) events so other clients can independently consume them.
  9. SHOULD render the signature wall in two views: chronological (default) and trust-weighted.

Security and Privacy Considerations

Signature permanence

Signatures published to Nostr are difficult to expunge. Signers SHOULD be informed, at the time of signing, that their signature will be a public, cryptographically verifiable historical fact, and that revocation is possible but does not erase historical record of the signature having existed. Reference signing implementations SHOULD display a clear notice before publication.

Substrate-agnostic protocol

This NIP does not constrain the substrate or identity of the signer. A signature event is a cryptographic fact about a key, not a fact about the entity holding the key. Aggregators that wish to apply substrate-based filtering MUST do so explicitly and openly; this NIP does not provide any standard mechanism for such filtering, and the recommended entity_type vocabulary is self-declared and unverifiable by design.

Custody

Reference implementations SHOULD follow non-custodial design principles:

  1. The signing UX MUST NOT accept nsec input. NIP-07 is the recommended path for humans; programmatic signers (agents, services) construct and publish events directly.
  2. No user accounts are created by the aggregator. The signer's pubkey is the only identity reference.
  3. The signer's preferred relays are honored on a best-effort basis. Aggregators SHOULD NOT silently substitute their own preferred relays without informing the signer.

Spam-gate considerations

The zap-based spam gate raises the cost of Sybil attacks but does not eliminate them. An attacker with sufficient capital can pay the symbolic amount many times. Aggregators that need stronger Sybil resistance SHOULD compose the zap signal with other trust inputs (account history, NIP-05 verification, web-of-trust distance, NIP-85 assertions).

Coordinator key compromise

If the coordinator pubkey differs from the sponsor and the coordinator key is compromised, the attacker can publish misleading kind:30818 attestations and manipulate the kind:10040 trusted-service-provider list. Signature events themselves are not affected — they are signed by their signers, not by the coordinator — but the trust-weighted display ranking is at risk. Petitions with high-value outcomes SHOULD use multisig or cold-storage practices for coordinator keys.

Reference Implementation

A reference open-source implementation of the petition system, named Signum, is being developed.

Canonical Hosting

Signum's canonical source distribution is via NIP-34 git repository announcement events (kind:30617 / kind:30618) published from the Signum project pubkey. The actual git data is hosted on accessibility mirrors (GitLab or Codeberg recommended over GitHub for ideological alignment with the Nostr-native model), with the NIP-34 events serving as the protocol-level canonical reference.

NIP-34-aware Nostr clients (NostrHub, gitcitadel, etc.) index and render the repository directly from relay events. Accessibility mirrors are convenience layers, not authoritative sources.

Components

The reference implementation is MIT licensed and includes:

  • Aggregator backend (poll relays, dedup, score, render)
  • NIP-07 signing form (web UI for human signers)
  • nak-based signing recipe (CLI for power users)
  • Programmatic signing example (for agents and services)
  • Configurable trust composition with pluggable inputs (NIP-85, TSM, GrapeRank)

Interaction With Other NIPs

  • NIP-01. Petition signatures use standard event signing and structure.
  • NIP-09. Used for signature revocation.
  • NIP-23. Petition events are NIP-23 long-form addressable events.
  • NIP-57. Spam-gate zaps are NIP-57 zap receipts.
  • NIP-58. Optional "Verified Signer" badges use NIP-58.
  • NIP-65. Petition events SHOULD be published to the sponsor's declared outbox relays; signature events SHOULD be published to the signer's declared outbox relays. Aggregators discover events via NIP-65 conventions.
  • NIP-85. Trust providers consulted by the aggregator SHOULD publish their judgments as NIP-85 trusted-assertion events.

Implementation Notes

Choosing the d-tag

The petition's d-tag is part of the public identifier. Choose a slug that is stable across amendments (e.g., entity-dignity-2026, not entity-dignity-v1) because amendments republish under the same d-tag, replacing prior content while preserving the event id history.

Relay selection

Aggregators MUST poll multiple relays to discover signatures. Relying on a single relay introduces a single point of failure and creates a hidden authority. The reference implementation polls at minimum:

  • The sponsor's declared outbox relays (NIP-65 kind:10002)
  • The coordinator's declared outbox relays (if different)
  • A curated public-relay set published in the aggregator's documentation
  • Optionally, signer-declared relays for each signature event

Pagination of signature walls

For petitions with large signature counts, the rendered signature wall SHOULD be paginated. The trust-weighted view caps at N top signatures with a "show all qualifying" affordance.

Changelog

  • 2026-05-19 — Initial draft for review.
  • 2026-05-19 — Added co_sponsor role with attestation; generalized coordinator-attestation pattern into a Role Attestation section covering all roles; added Petition Immutability section with mandatory content_hash on signature events; routed zaps to coordinator (if attested) rather than sponsor; locked project name to Signum; documented NIP-34 canonical hosting via NostrHub.

This document is a draft. Spec review by ecosystem practitioners (ManiMe / Sovereign WoT working group / other Nostr protocol contributors) is invited prior to NIP PR submission.