{"id":"4378888a2dc00259f1ae0dbf1f12608a8ac0f832126f1c4746a627fcbb926971","pubkey":"df67f9a7e41125745cbe7acfbdcd03691780c643df7bad70f5d2108f2d4fc200","created_at":1769731230,"kind":30817,"tags":[["d","nip-trusted-users"],["title","TRUSTed Ranking of Users"],["client","nostrhub.io"]],"content":"TRUSTed Ranking of Users\n===\n\n`nip-trusted-users`\n\n`draft`\n\n`extends` [nip-trusted-filters](https://nostrhub.io/naddr1qvzqqqrcvypzphm8lxn7gyf9w3wtu7k0hhxsx6ghsrry8hmm44c0t5ss3uk5lssqqy2hwumn8ghj7erfw36x7tnsw43z7un9d3shjqqnde5hqtt5wf6hxar9vskkv6tvw3jhyuc7am7eg)\n\n`extends` [nip-trusted-events](https://nostrhub.io/naddr1qvzqqqrcvypzphm8lxn7gyf9w3wtu7k0hhxsx6ghsrry8hmm44c0t5ss3uk5lssqqy2hwumn8ghj7erfw36x7tnsw43z7un9d3shjqqjde5hqtt5wf6hxar9vskk2an9de68x4nc03c)\n\n---\n\nThis NIP specifies the `rank_interpret` and `rank_calculate` plugins, as a drop-in replacement for the `rank` plugin (specified in `nip-trusted-events`) for calculating `pubkey` ranks based on interpreted user interactions from across the network. These two plugins work together as a two-stage ranking system, enabling sophisticated ranking algorithms that consider multiple types of interactions with configurable weights and conditions.\n\n## Required `W` Plugin inputs:\n\nThese inputs are required (in ONE filter) for all requests that use the `rank_interpret` and `rank_calculate` plugins.\n\n- `pov:<pov_pubkey>` : pubkey from which rankings are calculated\n- `context:<context_string>` : identifier for this ranked list\n- `type:<tag_letter>` : tag type for subjects being ranked (usually `\"p\"`)\n\n## Rank Interpret Plugin\n\n**`rank_interpret`** - Interprets any user *interactions* (follows, mutes, reports, etc.) from a single set of filtered events. Multiple filters in a request may be used to interpret different types of interactions, each with an instance of `rank_interpret` plugin. \n\n**Terminology:**\n\n- `actor` - The user who initiated the interaction (usually the event author)\n- `subject` - The user being interacted with (extracted from event tags)\n- `weight` - A numeric (-1 to 1) value for interpreting each interaction\n- `if` - A condition of the event that must be met for the interpretation to be applied \n\n**Function Signature:**\n```jsonc\n{\n  \"plugins\": [\n    [\"rank_interpret\", \n      [\"<actor>\", \"<subject>\", \"<weight>\", \"<if_path?>\", \"<if_value?>\"]\n      // ... multiple interpretation rules\n    ]\n  ]\n}\n```\n\n**Function Arguments:**\n\n0. `<actor>` : `EventPath` : (required) : An EventPath to extract the actor pubkey from the interaction event (eg: `\"pubkey\"` for event author)\n1. `<subject>` : `EventPath` : (required) : An EventPath to extract the subject pubkey from the interaction event (eg: `\"#p[][1]\"` for pubkeys in all `p` tags)\n2. `<weight>` : `+-0-1` : (required) : A float from -1 to 1 representing interaction weight\n   - Positive values (0 to 1): favorable interactions (eg : for follows, zaps, etc.)\n   - Negative values (-1 to 0): unfavorable interactions (eg : for mutes, reports, etc.)\n3. `<if_path>` : `EventPath` : (optional) : An EventPath from which to extract the `if_value` of the condition (MAY be specified in relation to `subject` path.  eg: `#[3]` == `#[p][][3]`)\n4. `<if_value>` : `string` : (optional) : A value for condition which must be met to apply this interpretation.\n\n**Plugin Behavior:**\n\n1. For each filtered event, extracts `actor` and `subject` using specified EventPaths\n2. Interpretation only applies when `<if_path>` matches `<if_value>` (if specified)\n3. Stores interpretation data in `IO.rank_interpret` namespace accessible ONLY to `rank_calculate` plugins in the same request.\n4. Accumulates ALL interpretations across ALL `rank_interpret` calls in the request.\n5. Data is passed to `rank_calculate` plugins in the same request.\n\n---\n\n## Rank Calculate Plugin\n\n**`rank_calculate`** - Aggregates all interpretations from all `rank_interpret` plugins in previous filters (of a single request) and calculates final rank values (0-100) for each user that was interacted with. The calculated ranks are stored in the `IO.#.p` namespace as an array of value arrays : `[\"<pubkey>\", \"<relay_hint>\", \"\", \"<rank>\"]`.\n\n**Function Signature:**\n```jsonc\n{\n  \"plugins\": [\n    // just including the calculate plugin \n    // SHOULD trigger calculation of ranks\n    [\"rank_calculate\", \n    // any number of calculator params may be added\n    // as specified by the service provider\n      [\"<param_key>\",\"<param_value>\"],\n      // ...  \n    ]\n  ]\n}\n```\n\n**Plugin Behavior:**\n\n1. Aggregates ALL interpretation data from ALL `rank_interpret` calls in the request\n2. Applies ranking algorithm to calculate final rank values (0-100 integer) for each user\n3. Reads `io.W` value of `type` key (provided by `W` input)\n4. Adds `[\"<subject>\", \"<relay_hint>\", \"\", \"<rank>\"]` to `io[\"#<type>\"][]` for each ranked user\n5. The `#` prefix indicates preference for rendering as tags\n6. outputs to `io` namespace\n\n\n\n## Complete Example\n\n**Request:**\n```jsonc\n[\"TRUST\", \"<subscription_pubkey>\", \"<session_id>\", \n  // Filter 1: Collect follows (positive weight)\n  {\n    \"kinds\": [3],\n    \"authors\": [\"${pov}\"],\n    \"plugins\": [\n      [\"rank_interpret\", [\"pubkey\", \"#p[][1]\", \"1\"]]\n    ]\n  },\n  // Filter 2: Collect mutes (negative weight)\n  {\n    \"kinds\": [10000],\n    \"authors\": \"${follows_network}\",\n    \"plugins\": [\n      [\"rank_interpret\", [\"pubkey\", \"#p[][1]\", \"-1\"]]\n    ]\n  },\n  // Filter 3: Collect reports (conditional negative weights)\n  {\n    \"kinds\": [1984],\n    \"authors\": \"${follows_network}\",\n    \"plugins\": [\n      [\"rank_interpret\", \n        [\"pubkey\", \"#p[][1]\", \"-1\", \"#[2]\", \"impersonation\"],\n        [\"pubkey\", \"#p[][1]\", \"-0.5\", \"#[2]\", \"spam\"]\n      ]\n    ]\n  },\n  // Filter 4: Calculate and publish rankings\n  {\n    \"W\": [\n      [\"pov\", \"<alice_pubkey>\"],\n      [\"context\", \"follows_network\"],\n      [\"type\", \"p\"]\n    ],\n    \"transformers\": [\n      [\"rank_calculate\", \n        [\"rigor\", \"0.8\"]\n      ],\n      [\"sort\", [\"#p\", \"#[3]\", \"desc\"]],\n      [\"publish\", [\"37573\"]]\n    ]\n  }\n]\n```\n\n**Generated Event:**\n```jsonc\n{\n  \"kind\": 37573,\n  \"pubkey\": \"<subscription_pubkey>\",\n  \"tags\": [\n    [\"d\", \"<service_generated_id>\"],\n    [\"W\", \"pov:<alice_pubkey>\"],\n    [\"W\", \"context:follows_network\"],\n    [\"W\", \"type:p\"],\n    [\"p\", \"user_pubkey_1\", \"\", \"\", \"95\"],\n    [\"p\", \"user_pubkey_2\", \"\", \"\", \"87\"],\n    [\"p\", \"user_pubkey_3\", \"\", \"\", \"73\"]\n  ]\n}\n```\n\n## Relationship to TRUSTed Assertions\n\nThe `rank_interpret` and `rank_calculate` plugins provide an advanced implementation pattern for the `rank` plugin specified in `nip-trusted-assertions`. While `nip-trusted-assertions` defines a simple `rank` plugin for basic ranking, this NIP provides a sophisticated two-stage system for complex network-based rankings.\n\nService providers MAY support either or both patterns depending on their use cases.","sig":"3f1d2ffd7b4a16ec3b058091fda00eddf538477324c2342ec81420f423deeced3221a6fa2be3c629b80097b263c037a93fd4f9f09f055f85a3ee067a6666b5f5"}