Skip to content

Software applications events#1336

Draft
franzaps wants to merge 25 commits intonostr-protocol:masterfrom
franzaps:applications
Draft

Software applications events#1336
franzaps wants to merge 25 commits intonostr-protocol:masterfrom
franzaps:applications

Conversation

@franzaps
Copy link
Contributor

@franzaps franzaps commented Jun 29, 2024

Rendered

This event represents an application as used in Zapstore. It is actively being used in a production setting for many months already.

This relates to NIP-51 (kind 30063), those artifact sets point to their application (this event, kind 32267).

Feedback welcome

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Jun 29, 2024

hum.. isn't it possible to merge this with kind 31990? Kind 31990 is insufficiently defined on NIP-89 but most apps already have their entry due to https://nostrapp.link/

We could just add the additional tags needed by zap.store to that definition.

@franzaps
Copy link
Contributor Author

NIP-89 is for apps that handle nostr events, isn't it? It's not at all what I'm defining here. In fact, 90%+ of the apps on zap.store do not handle nostr events.

It feels very contrived to try to fit this simple definition on the complexity of NIP-89.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Jun 29, 2024

Yes, that's what NIP-89 needed it for, but those app definitions don't need to exist to solely respond to Nostr events. Actually, I believe most apps don't event that "response" field setup correctly. Right now they are just there to receive reviews.

DVMs also reuse the same kind to define their applications.

Reusing the kind doesnt mean you have to implement NIP-89 to support yours.

@franzaps
Copy link
Contributor Author

franzaps commented Jun 29, 2024

Are you saying I can keep my schema as-is and change 32267 to 31990? In such case I would have to change content which will break other NIP-89 clients.

Or do you mean I should stuff all my metadata into a stringified metadata and put it in content?

@vitorpamplona
Copy link
Collaborator

Hum.. yeah I missed the content discrepancy.

@pablof7z, do you see a possibility of merging those two?

Or are we going to have to define our apps in two places?

@franzaps
Copy link
Contributor Author

Do you know what is the rationale for putting stringified JSON in content (unless it has to be encrypted)? I've noticed the pattern in several places

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Jun 29, 2024

Do you know what is the rationale for putting stringified JSON in content

Dumb decisions. They probably just copied how kind 0 works :(

@franzaps
Copy link
Contributor Author

franzaps commented Jul 1, 2024

I also need data to be in tags for full text indexing purpose.

31990 seems built for something else which is fine: all apps can sign a 32267 and if they want nostr interop also sign a 31990.

I will keep using kind 32267 unless there's a better alternative to describe an application

@DanConwayDev
Copy link
Contributor

Love to see this and look forward to adding releases to nip34 clients.

Instead of referencing a nip34 announcement event in repository tag it should be referenced with an a tag so it will be indexed by relays. clients should look for an a tag with 30617 kind if repository is omitted.

The release event:

  1. should be moved into this nip from the example section of nip51.
  2. should be immutable and not a replaceable event. then trust attestations could be placed on the event eg. validation that the checksums of a reproducible build match.
  3. should include an optional ["commit-id","<SHA1-commit-id-used-to-build-release>"] tag

From a style point of view: I see most nips describe events using jsonc rather than a table of tags, which is easier to read. Is this now the standard?

lastly, the app event could support the maintainers tag like nip34 announcements This means clients could optionally interpret app events by the pubkeys listed with identical d tags as referring to the same app. ["maintainers", "<other-recognized-maintainer>", ...]

@franzaps
Copy link
Contributor Author

franzaps commented Jul 3, 2024

Love to see this and look forward to adding releases to nip34 clients.

Looking forward too!

Instead of referencing a nip34 announcement event in repository tag it should be referenced with an a tag so it will be indexed by relays. clients should look for an a tag with 30617 kind if repository is omitted.

Sounds great

The release event:

1. should be moved into this nip from the example section of nip51.

Sure, I can do that

2. should be immutable and not a replaceable event. then trust attestations could be placed on the event  eg. validation that the checksums of a reproducible build match.

We're probably talking about different things. The release set is a NIP-51 replaceable event (kind 30063) that is simply a pointer to a set of software releases (binaries). Trust attestations should be applied to NIP-94 (kind 1063) events because they carry a checksum of the binaries. Moreover, if a developer made a mistake in the file collection or a typo in the release notes, it's useful that they can update the event.

3. should include an optional `["commit-id","<SHA1-commit-id-used-to-build-release>"]` tag

Sure - in kind 1063s

From a style point of view: I see most nips describe events using jsonc rather than a table of tags, which is easier to read. Is this now the standard?

I don't think we have a standard for whether to include tables or not. Other NIPs use bullet points.

lastly, the app event could support the maintainers tag like nip34 announcements This means clients could optionally interpret app events by the pubkeys listed with identical d tags as referring to the same app. ["maintainers", "<other-recognized-maintainer>", ...]

This is currently done via attribution p/zap tags. I think a better idea is to include maintainers in releases (not apps).

@bezysoftware
Copy link
Contributor

Do you know what is the rationale for putting stringified JSON in content

Dumb decisions. They probably just copied how kind 0 works :(

Sorry to go off topic, but what is so bad about putting stringified json in content? Why are tags better?

@franzaps
Copy link
Contributor Author

franzaps commented Jul 4, 2024

@bezysoftware I would ask what is good about putting stringified JSON in content. It makes no sense to encode JSON inside JSON for no gain (unless it needs to be encrypted) since values of that object are strings anyway. Tags can be indexed.

Copy link
Contributor

@DanConwayDev DanConwayDev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is a suggested update reflecting the comments you were receptive to

@franzaps
Copy link
Contributor Author

I rewrote good part of this NIP.

As suggested by @NielLiesmons application description should be a wiki article. With that, developers also get access to better tools for updating information.

Presented the tags in jsonc example format as suggested by @DanConwayDev

Lastly, made a clarification on NIP-89.

Events on relay.zap.store do not yet conform to this spec but will be migrated shortly.

@franzaps
Copy link
Contributor Author

Updated the NIP to reflect the usage on Zapstore.

Since it has been used for months now and it's pretty stable, can we get this merged?

@staab
Copy link
Member

staab commented Dec 10, 2024

Is this in use by anyone other than zap.store?

@franzaps
Copy link
Contributor Author

@staab Not that I'm aware of.

Other than, maybe, @Giszmo ?

@staab
Copy link
Member

staab commented Dec 10, 2024

Normally NIPs are merged once there's some compatibility that needs to be ensured. It's good to have it documented in a draft, but update here when there are other apps using the standard

@franzaps
Copy link
Contributor Author

This data structure will probably end up in NDK and used in Yana and probably in a relay-based community started by @NielLiesmons

@vitorpamplona
Copy link
Collaborator

This should be merged.

@staab
Copy link
Member

staab commented Jan 22, 2025

Are there 2+ clients?

@vitorpamplona
Copy link
Collaborator

I am putting in on Amethyst right now. We can wait for the next release if we don't have any other client using this yet.

@DanConwayDev
Copy link
Contributor

DanConwayDev commented Jan 22, 2025 via email

@staab
Copy link
Member

staab commented Jan 22, 2025

I am putting in on Amethyst right now.

That's good enough for me. Are you implementing as is?

@alltheseas
Copy link
Contributor

alltheseas commented Feb 2, 2026

suggested backwards compatible language extension

For Fran review:

 Convention: d tag with @lang suffix                                                                                                                                                                            
                                                                                                                                                                                                                 
  // Canonical app (default language)                                                                                                                                                                            
  {                                                                                                                                                                                                              
    "kind": 32267,                                                                                                                                                                                               
    "tags": [                                                                                                                                                                                                    
      ["d", "com.example.app"],           // No suffix = canonical                                                                                                                                               
      ["name", "Calculator"],                                                                                                                                                                                    
      ["L", "ISO-639-1"],                                                                                                                                                                                        
      ["l", "en", "ISO-639-1"]            // NIP-32 language label                                                                                                                                               
    ],                                                                                                                                                                                                           
    "content": "A fast calculator..."                                                                                                                                                                            
  }                                                                                                                                                                                                              
                                                                                                                                                                                                                 
  // Spanish translation (same or different publisher)                                                                                                                                                           
  {                                                                                                                                                                                                              
    "kind": 32267,                                                                                                                                                                                               
    "tags": [                                                                                                                                                                                                    
      ["d", "com.example.app@es"],        // @lang suffix = translation                                                                                                                                          
      ["name", "Calculadora"],                                                                                                                                                                                   
      ["L", "ISO-639-1"],                                                                                                                                                                                        
      ["l", "es", "ISO-639-1"],                                                                                                                                                                                  
      ["a", "32267:<pubkey>:com.example.app", "<relay-hint>"]  // Points to canonical                                                                                                                            
    ],                                                                                                                                                                                                           
    "content": "Una calculadora rápida..."                                                                                                                                                                       
  }                                                                                                                                                                                                              
                         

Context & Reasoning

  Why This Is The Best Path                                                                                                                                                                                      
  ┌─────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────┐                                                                                       
  │          Criterion          │                                      How It's Met                                      │                                                                                       
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤                                                                                       
  │ Original NIP spirit         │ Each Kind 32267 = one app description. No new kinds.                                   │                                                                                       
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤                                                                                       
  │ Future-proof                │ @lang scales to 1 or 500 languages. Add more anytime.                                  │                                                                                       
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤                                                                                       
  │ Backwards compatible        │ Old clients see "separate apps" (graceful degradation). New clients group by d prefix. │                                                                                       
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤                                                                                       
  │ Uses existing NIPs          │ NIP-32 (l tag), NIP-01 (a tag for reference)                                           │                                                                                       
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤                                                                                       
  │ Same publisher multi-lang   │ ✓ Different d tag = different event identity                                           │                                                                                       
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤                                                                                       
  │ Community translations      │ ✓ Different pubkey with same d@lang pattern                                            │                                                                                       
  ├─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────┤                                                                                       
  │ No NIP changes needed later │ Convention is extensible without protocol changes                                      │                                                                                       
  └─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────┘                                                                                       
  ---                                                                                                                                                                                                            
  Spec Addition (add to NIP-82)                                                                                                                                                                                  
                                                                                                                                                                                                                 
  ## Localized Application Metadata                                                                                                                                                                              
                                                                                                                                                                                                                 
  Applications MAY provide metadata in multiple languages using the `d` tag suffix convention:                                                                                                                   
                                                                                                                                                                                                                 
  - `["d", "<app-id>"]` - Canonical application (default/primary language)                                                                                                                                       
  - `["d", "<app-id>@<lang>"]` - Localized variant where `<lang>` is an ISO 639-1 code                                                                                                                           
                                                                                                                                                                                                                 
  Localized events SHOULD include:                                                                                                                                                                               
  - `["L", "ISO-639-1"]` and `["l", "<lang>", "ISO-639-1"]` tags per NIP-32                                                                                                                                      
  - `["a", "32267:<canonical-pubkey>:<app-id>", "<relay-hint>"]` referencing the canonical app                                                                                                                   
                                                                                                                                                                                                                 
  Clients SHOULD:                                                                                                                                                                                                
  - Query with `#l` filter to fetch user's preferred language                                                                                                                                                    
  - Group events by `d` tag prefix (before `@`) when displaying apps                                                                                                                                             
  - Prefer canonical (`d` without `@`) for non-localized fields (icon, releases)                                                                                                                                 
                                                                                                                                                                                                                 
  Example query for Spanish apps:                                                                                                                                                                                
  ```json                                                                                                                                                                                                        
  {"kinds": [32267], "#l": ["es"]}                                                                                                                                                                               
                                                                                                                                                                                                                 
  ---                                                                                                                                                                                                            
                                                                                                                                                                                                                 
  ### How It Works In Practice                                                                                                                                                                                   
                                                                                                                                                                                                                 
  **Publisher workflow (50 languages):**                                                                                                                                                                         
  com.example.app       → English (canonical)                                                                                                                                                                    
  com.example.app@es    → Spanish                                                                                                                                                                                
  com.example.app@zh    → Chinese                                                                                                                                                                                
  com.example.app@ar    → Arabic                                                                                                                                                                                 
  ... (47 more)                                                                                                                                                                                                  
                                                                                                                                                                                                                 
  **Client query:**                                                                                                                                                                                              
  ```jsonc                                                                                                                                                                                                       
  // User's locale is Spanish                                                                                                                                                                                    
  {"kinds": [32267], "#d": ["com.example.app", "com.example.app@es"], "#l": ["es", "en"]}                                                                                                                        
                                                                                                                                                                                                                 
  // Or discover all translations of an app                                                                                                                                                                      
  {"kinds": [32267], "#d": ["com.example.app", "com.example.app@*"]}  // If relay supports prefix matching                                                                                                       
                                                                                                                                                                                                                 
  // Or simpler: fetch by app-id prefix pattern in client                                                                                                                                                        
                                                                                                                                                                                                                 
  Client merge logic:                                                                                                                                                                                            
  1. Fetch canonical: com.example.app                                                                                                                                                                            
  2. Fetch translation: com.example.app@{userLang}                                                                                                                                                               
  3. Use translation's name/summary/content                                                                                                                                                                      
  4. Use canonical's icon/images/releases (non-localized fields)                                                                                                                                                 
                                                                                                            

What Gets Added to NIP-82                                                                                                                                                                                      
                                                                                                                                                                                                                 
  1. @lang suffix convention for d tag (~5 lines)                                                                                                                                                                
  2. Recommend NIP-32 labels for language (~3 lines)                                                                                                                                                             
  3. Recommend a tag to canonical (~3 lines)                                                                                                                                                                     
  4. Client behavior for grouping/querying (~10 lines)                                                                                                                                                           
                                                                                                                                                                                                                 
  Total: ~20 lines added to spec. No new kinds. No breaking changes. Scales forever.                                                                                                                             
                                                                                                                                                                                                                 
  ---                                                                                                                                                                                                            
  Optional Extensions (add later without NIP changes)                                                                                                                                                            
  ┌──────────────────────────┬────────────────────────────────────────────────────────┬─────────────────────────┐                                                                                                
  │        Extension         │                          How                           │          When           │                                                                                                
  ├──────────────────────────┼────────────────────────────────────────────────────────┼─────────────────────────┤                                                                                                
  │ Machine translation flag │ ["l", "es", "ISO-639-1", "mt"] (4th element)           │ If MT becomes common    │                                                                                                
  ├──────────────────────────┼────────────────────────────────────────────────────────┼─────────────────────────┤                                                                                                
  │ Translation quality      │ NIP-32 label: ["l", "verified", "translation-quality"] │ If quality tiers needed │                                                                                                
  ├──────────────────────────┼────────────────────────────────────────────────────────┼─────────────────────────┤                                                                                                
  │ Translator attribution   │ ["p", "<translator-pubkey>"]                           │ Already supported       │                                                                                                
  └──────────────────────────┴────────────────────────────────────────────────────────┴─────────────────────────┘      

from zapstore/zapstore#298 (comment)

@alltheseas
Copy link
Contributor

Is this in use by anyone other than zap.store?

notedeck implemented for auto-update use case (damus-io/notedeck#1326)

tracker is here: nostrability/nostrability#277

@alltheseas
Copy link
Contributor

ditto also added supported today for:

  1. rendering kind 32267 app events in-feed
  2. fetching releases kind 30063 from ZS relay

nostrability/nostrability#277

cc @alexgleason

@alltheseas
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.