diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f7dabe7 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,60 @@ +# Repository Guidance + +This repository contains implementation-sensitive protocol text. Treat the current specification as already implemented by real applications. + +## Core Rule + +Do not change the meaning of current specification material during structural refactors. + +Preserve: + +- event kind numbers +- tag names and tag ordering where shown in examples +- tag array shapes +- JSON payload shapes +- field names +- required/optional semantics +- status and type values +- examples +- MUST, SHOULD, and MAY language +- links to upstream specs and prior work + +## Current Compatibility Snapshot + +[SPEC.md](SPEC.md) is the contiguous current specification. It was copied from the pre-refactor root README and should remain available for implementers who need the old single-document shape. + +If split docs disagree with [SPEC.md](SPEC.md), treat [SPEC.md](SPEC.md) as the compatibility source for the current protocol. + +## Structural Refactors + +Structural PRs may: + +- move or copy text unchanged +- add navigation +- add compatibility notes +- add history and acknowledgments +- add clearly marked explanatory material +- add clearly marked proposal workspaces + +Structural PRs must not: + +- invent new Nostr kinds +- rename existing tags +- rewrite examples +- change payment, order, delivery, listing, review, or merchant-preference semantics +- make escrow mandatory +- make any marketplace a required custodian of funds +- collapse external proposals into this spec as if they are already canonical + +## Normative Labels + +Use explicit labels: + +- Normative: current spec material or future accepted protocol requirements. +- Explanatory: reader guidance that does not redefine protocol behavior. +- Historical: prior work and acknowledgments. +- Experimental: active proposals, design space, or integration notes. + +## Agent Notes + +Before editing, inventory kind numbers, tag names, examples, and normative keywords in affected sections. After editing, compare them again. Prefer exact copies over paraphrases when transposing current spec text. diff --git a/README.md b/README.md index 2ba8eba..cbc7b4d 100644 --- a/README.md +++ b/README.md @@ -1,837 +1,49 @@ -Marketplace Protocol ---------------------------- +# Open Markets Specification -`draft` +Open Markets is a specification workspace for decentralized marketplaces on Nostr. -A protocol specification for decentralized marketplaces on Nostr that provides an interoperable, full-featured e-commerce framework. +This repository currently preserves the existing e-commerce marketplace protocol exactly while reorganizing it into clearer navigation paths for future work. The refactor is a transposition, not a recomposition: existing event kinds, tag shapes, payload structures, examples, and normative requirements remain unchanged. -## Table of Contents -1. Protocol Requirements -2. Core Protocol Components -3. Events and Kinds -4. Order Communication Flow and Payment Processing -5. Product Reviews -6. Implementation Guidelines +## Current Spec -## 1. Protocol Requirements +- [SPEC.md](SPEC.md) is the contiguous compatibility snapshot of the current specification. +- [docs/compatibility.md](docs/compatibility.md) lists the invariants this repository must preserve. +- [docs/architecture.md](docs/architecture.md) maps the current spec into the four organizational pillars. +- [lanes/ecommerce.md](lanes/ecommerce.md) preserves the current e-commerce lane as the first fully expressed market lane. -The protocol defines both required core components and optional features to support diverse marketplace needs. +## Pillars -### Required Components -Implementations MUST support the following core features: +The repo is organized around four broad homes for current and future Open Markets work: -- Product listing events (Kind: 30402) -- Product collection events (Kind: 30405) for product-to-collection references -- Merchant's preferences -- Order communication and processing via [NIP-17](17.md) encrypted messages +- [Items](pillars/items.md): listings, collections, drafts, reviews, metadata, discovery, categorization, and pricing. +- [Orders](pillars/orders.md): buyer/seller intent, order creation, communication, status, cancellation, and receipts. +- [Payments](pillars/payments.md): merchant preferences, payment requests, payment proofs, invoices, receipts, and future payment rails. +- [Delivery](pillars/delivery.md): shipping options, pickup, shipping updates, digital delivery, services, rides, lodging, and fulfillment. -### Optional Components -These features MAY be implemented based on specific marketplace needs: +Only the current e-commerce material is normative today. Future market lanes can be added without changing current behavior. -- Extended product metadata -- Shipping options (Kind: 30406) -- Product collections (Kind: 30405) -- Drafts following [NIP-37](37.md) -- Product reviews (Kind: 31555) -- Service assisted order and payment processing +## Normative Status -#### Watch-only clients -Watch-only clients are applications that allow users to display products without implementing full e-commerce capabilities. These clients don't need to support all required components - product rendering alone can be sufficient. However, ideally, they should also handle logic for looking up collections, reviews, and shipping options. Support for order communication using [NIP-17](17.md) is optional. +- Normative: [SPEC.md](SPEC.md) and copied current-spec sections in the pillar and lane files. +- Explanatory: docs under [docs/](docs/) unless explicitly marked otherwise. +- Historical: [docs/history.md](docs/history.md). +- Experimental/proposal: [proposals/](proposals/). -## 2. Core Protocol Components +When there is any ambiguity, [SPEC.md](SPEC.md) controls for current compatibility. -### Core Flows -1. Merchant Preferences - - Application preferences via [NIP-89](89.md) - - Payment method preferences via kind `0` tags +## Prior Work -2. Order Processing - - Encrypted buyer-seller communication - - Status updates and confirmations - -3. Shipping - - Option definition and pricing - - Geographic restrictions - -4. Payment - - Multiple payment methods - - Verification and receipts +This repository builds on and preserves links to the current Nostr commerce design space: -Standard e-commerce flow: -1. Product discovery -2. Cart addition -3. Merchant preference verification -4. Shipping calculation -5. Payment processing -6. Order confirmation -7. Encrypted message follow-up +- [Gamma Markets market-spec](https://github.com/GammaMarkets/market-spec) +- [NIP-99 classified listings](https://github.com/nostr-protocol/nips/blob/master/99.md) +- [NIP-15 marketplace](https://github.com/nostr-protocol/nips/blob/master/15.md) +- [nostr-commerce-skill](https://github.com/welliv/nostr-commerce-skill) +- [Colabonate NIP-115 draft](https://github.com/Colabonate/nips/blob/colabonate-freedom-protocol/115.md) +- [nostr-protocol/nips PR 2323](https://github.com/nostr-protocol/nips/pull/2323) +- [Pontmore PIP-00 agent definition](https://github.com/pontmore/protocol/blob/main/PIP-00-agent-definition.md) +- [Switchboard escrow architecture](https://github.com/samuelralak/switchboard/blob/master/docs/escrow-architecture.md) -### Merchant Preferences -Merchants MAY specify preferences for how they want users to interact with them, including which applications to use and payment methods to accept. These preferences ensure a consistent experience and streamline operations. Merchants indicate their preferences through two mechanisms: +## Contributing -1. Application Preferences ([NIP-89](89.md)): -- The recommended application MUST publish a kind `31990` event -- The merchant MUST publish a kind `31989` event recommending that application - -2. Payment Preferences: -- Set via `payment_preference` tag in the merchant's kind `0` event -- Valid values: `manual | ecash | lud16` -- Defaults to `manual` if not specified - -Applications implementing this NIP MUST handle preferences as follows: - -1. When `payment_preference` is `manual`: -- If merchant recommends an app: MUST direct users to that app -- If no app recommendation: Use traditional interactive flow (buyer places order and waits for merchant's payment request) - -2. When `payment_preference` is `ecash` or `lud16`: -- If merchant recommends an app: SHOULD direct users there first, but they MAY also offer to continue if compatible with the payment preference -- If no recommendations: Use specified payment method directly - -3. When no preferences are set: -- Use traditional interactive flow - - Buyer sends order - - Wait for merchant's payment request - -Buyers can verify merchant preferences by: -- Checking kind `31990` events for recommended applications -- Checking kind `0` events for payment preferences - -This verification helps buyers follow merchant-approved paths and avoid potential scams or poor experiences. - -## 3. Events and Kinds - -### Product Listing (Kind: 30402) - -Products are the core element in a marketplace. Each product listing MUST contain basic metadata and MAY contain additional details. Their configuration is the source of truth, overriding other possible configurations of other market elements such as collections, no configuration is cascaded to products, they MUST explicitly reference an attribute to inherit it. - -**Content**: Product description, markdown is allowed -**Required tags**: -- `d`: Unique product identifier for referencing the listing -- `title`: Product name/title for display -- `price`: Price information array `[, , ]` - - amount: Decimal number (e.g., "10.99") - - currency: ISO 4217 code (e.g., "USD", "EUR") - - frequency: Optional subscription interval using ISO 8601 duration units (e.g. 'D' for daily, 'W' for weekly, 'Y' for yearly). - -**Optional tags**: -- Product Details: - - `type`: Product classification `[, ]` - - type: "simple", "variable", or "variation" - - format: "digital" or "physical" - - Default/if not present: type: "simple", format: "digital" - - `visibility`: Display status ("hidden", "on-sale", "pre-order"). Default/if not present: "on-sale" - - `stock`: Available quantity as integer - - `summary`: Short product description - - `spec`: Product specifications `[, ]`, can appear multiple times - -- Media: - - `image`: Product images `[, , ]`, MAY appear multiple times - - url: Direct image URL - - dimensions: Optional, in pixels, "x" format, if not present the place in the array should be respected by using an empty string `""` - - sorting order: Optional integer for order sorting. Values are sorted from lowest to highest, independent of starting value (not restricted to start with 0 or 1) - -- Physical Properties: - - `weight`: Product weight `[, ]` using ISO 80000-1 - - `dim`: Dimensions `[xx, ]` using ISO 80000-1 - -- Location: - - `location`: Human-readable location string or collection coordinates - - `g`: Geohash for precise location lookup or collection coordinates - -- Organization: - - `t`: Product categories/tags, MAY appear multiple times - - `a`: Product reference "30402::", MUST appear only once to reference parent products in a variable/variation configuration - - `a`: Collection reference "30405::", MAY appear multiple times - - `shipping_option`: Shipping options, MAY appear multiple times - - Format: "30406::" for direct options - - Format: "30405::" for collection shipping - - `extra-cost`: Optional third element in the array, to add extra cost (in the product's currency) for the shipping method. In case of reference a collection the extra cost should be applied to all shipping options from the collection. - -```jsonc -{ - "kind": 30402, - "created_at": , - "content": "", - "tags": [ - // Required tags - ["d", ""], - ["title", ""], - ["price", "", "", ""], - - // Product details - ["type", "", ""], // Defaults: simple, digital - ["visibility", ""], // Default: on-sale - ["stock", ""], // Available quantity - ["summary", ""], - - // Media and specs - ["image", "", "", ""], - ["spec", "", ""], // Product specifications (e.g., "screen-size", "21 inch"). MAY appear multiple times - - // Physical properties (for shipping) - ["weight", "", ""], // ISO 80000-1 units (g, kg, etc) - ["dim", "xx", ""], // ISO 80000-1 units (mm, cm, m) - - // Location - ["location", "
"], - ["g", ""], - - // Classifications - ["t", ""], - - // References - ["shipping_option", "<30406|30405>::", ""], // Shipping options or collection, MAY appear multiple times - ["a", "30405::"] // Product collection - ] -} -``` - -#### Notes -1. Product Configuration: - - Products can be simple, variable (with options), or variations of variable products - - Digital products skip shipping requirements - - Visibility controls product display status - -2. Variable products: - - The parent or "root" product should use `variable` as value for `type` - - The variations of the parent product should use `variation` as value for `type`. - - Variations MUST include an `a` tag pointing to the `variable` parent product. - -2. Shipping Rules: - - Shipping options can be defined directly by pointing to a shipping event, or inherited from collections - - If the product specifies product-specific shipping, and also from a collection, shipping options MUST be merged. - -3. Collections and Categories: - - Products can refer to one o multiple collections using `a` tags, whether or not they are part of it, for discoverability purposes. - - Categories ("t" tags) aid in discovery and organization - -4. Location Support: - - Optional location data aids in local marketplace features, they can point to a collection event to inherit it's value - - Geohash enables precise location-based searches, they can point to a collection event to inherit it's value - -### Product Collection (Kind: 30405) -A specialized event type using [NIP-51](51.md) like list format to organize related products into groups. Collections allow merchants or any user to create meaningful product groupings and share common attributes that products can also reference, establishing one-to-many relationships. - -**Content**: Optional collection description - -**Required tags**: -- `d`: Unique collection identifier -- `title`: Collection display name/title -- `a`: Product references `["a", "30402::"]` - - Multiple product references allowed - - References must point to valid product listings - -**Optional tags**: -- Display: - - `image`: Collection banner/thumbnail URL - - `summary`: Brief collection description - -- Location: - - `location`: Human-readable location string - - `g`: Geohash for precise location lookup - -- Reference Options: - - `shipping_option`: Available shipping options `["shipping_option", "30406::"]`, MAY appear multiple times - -```jsonc -{ - "kind": 30405, - "created_at": , - "content": "", - "tags": [ - // Required tags - ["d", ""], - ["title", ""], - ["a", "30402::"], // Product reference - - // Optional tags - ["image", ""], - ["summary", ""], - - // Location - ["location", ""], - ["g", ""], - - // Reference Options - ["shipping_option", "30406::"], // Available shipping options, MAY appear multiple times - ] -} -``` - -#### Notes -1. Collection Management: - - Collections can contain any number of products - - Products can belong to multiple collections - -2. Reference Model: - - Collection settings (shipping, location, geohash) serve as references only - - Products MUST explicitly reference collection resources to inherit collection attributes (e.g. shipping, location, geohash). - - No automatic cascading of settings to products - -3. Location Support: - - Optional location data helps with marketplace organization - - Enables geographic grouping of related products - -### Drafts -Products and collections can be saved as private drafts while being prepared for publication. This allows merchants to work on listings before making them publicly visible. Implementation MUST follow [NIP-37](https://github.com/nostr-protocol/nips/blob/master/37.md) for draft management. - -### Shipping Option (Kind: 30406) -A specialized event type for defining shipping methods, costs, and constraints. Shipping options can be published by merchants or third-party providers (delivery companies, DVMs, etc.) and referenced by product listings or collections. - -**Content**: Optional human-friendly shipping description - -**Required tags**: -- `d`: Unique shipping option identifier -- `title`: Display title for the shipping method -- `price`: Base cost array `[, ]` -- `country`: Array of ISO 3166-1 alpha-2 country codes `[, , ...]` -- `service`: Service type ("standard", "express", "overnight", "pickup") - -**Optional tags**: -- Extra details: - - `carrier`: The name of the carrier that will be used for the delivery -- Time and Location: - - `region`: Array of ISO 3166-2 region codes for which shipping method is available `[, , ...]` - - `duration`: Delivery window `[, , ]` using ISO 8601 duration units - - min: Minimum delivery time - - max: Maximum delivery time - - unit: "H" (hours), "D" (days), "W" (weeks) - - `location`: Physical address for pickup - - `g`: Geohash for precise location - -- Constraints: - - `weight-min`: Minimum weight `[, ]` (ISO 80000-1) - - `weight-max`: Maximum weight `[, ]` - - `dim-min`: Minimum dimensions `[xx, ]` - - `dim-max`: Maximum dimensions `[xx, ]` - -- Price Calculations: - - `price-weight`: Per weight pricing `[, ]` - - `price-volume`: Per volume pricing `[, ]` - - `price-distance`: Per distance pricing `[, ]` - -```jsonc -{ - "kind": 30406, - "created_at": , - "content": "", - "tags": [ - // Required tags - ["d", ""], - ["title", ""], - ["price", "", ""], - ["country", "", "...", "..."], // Array of country codes - ["service", ""], - - // Extra details - ["carrier",""] - - // Time and Location - ["region", "", "...", "..."], // Array of region codes - ["duration", "", "", ""], // ISO 8601 duration units (H/D/W) - ["location", "
"], - ["g", ""], - - // Constraints - ["weight-min", "", ""], - ["weight-max", "", ""], - ["dim-min", "xx", ""], - ["dim-max", "xx", ""], - - // Price Calculations - ["price-weight", "", ""], - ["price-volume", "", ""], - ["price-distance", "", ""] - ] -} -``` - -#### Implementation Examples - -Local Pickup: -```jsonc -{ - "kind": 30406, - "created_at": 1703187600, - "content": "Downtown Store Pickup", - "tags": [ - ["d", "downtown-pickup"], - ["title", "Downtown Store Pickup"], - ["price", "0", "USD"], - ["country", "US"], - ["region", "US-FL"], - ["service", "pickup"], - ["location", "123 Main St, Downtown, FL"], - ["g", "dhwm9c4ws"] - ] -} -``` - -Standard Shipping: -```jsonc -{ - "kind": 30406, - "created_at": 1703187600, - "content": "Standard Regional Shipping", - "tags": [ - ["d", "standard-regional"], - ["title", "Standard Shipping"], - ["price", "5.99", "USD"], - ["country", "US"], - ["region", "US-FL"], - ["service", "standard"], - ["duration", "24", "72", "H"], // 24-72 hours delivery window - ["weight-max", "30", "kg"], - ["dim-max", "120x60x60", "cm"], - ["price-weight", "0.75", "USD", "kg"] - ] -} -``` - -#### Notes -1. Event Management: - - Create separate events for each distinct shipping option - - Each option needs a unique `d` tag identifier - - Merchants can reference third-party shipping options - -2. Shipping Rules: - - Physical pickup requires location and/or geohash - - Weight/dimension constraints use ISO 80000-1 units - -3. Client Behavior: - - Group options by service type and location - - Use geohash for distance-based sorting - - Validate package constraints before offering options - -## 4. Order Communication Flow and Payment Processing - -Order processing and status updates use [NIP-17](17.md) encrypted direct messages, with three event kinds serving different purposes: - -- Kind `14`: Regular communication between parties - - General inquiries and responses - - Order clarifications - - Subject can be order ID or empty - -- Kind `16`: Order processing and status. These messages include a `type` field that indicates the specific kind of message - - Order creation and details. `type`: 1 - - Payment requests. `type`: 2 - - Status updates. `type`: 3 - - Shipping information. `type`: 4 - -- Kind `17`: Payment receipts and verification - -Message direction is determined by the author, and `p` tag: -- Buyer → Merchant: event author is the buyer, `p` tag contains merchant's pubkey -- Merchant → Buyer: event author is the merchant, `p` tag contains buyer's pubkey - -The payment request flow can operate in two modes: -1. Direct: Merchant processes requests manually. Payment request is initiated by the merchant -2. Service-assisted: Merchant's payment service handles requests. Payment request is initiated by the buyer - -### Message Types -#### 1. Order Creation -Sent by buyer to initiate order process. - -**Content:** (Optional) Human readable order notes or special requests - -**Required tags:** -- `p`: Merchant's public key -- `subject`: Human-friendly subject line for order information -- `type`: Must be "1" to indicate order creation -- `order`: Unique identifier for the order -- `amount`: Total order amount in satoshis -- `item`: Product reference in format "30402::" with quantity. MAY appear multiple times - -**Optional tags:** -- `shipping`: Reference to shipping option "30406::" -- `address`: Shipping address details -- `email`: Customer email for contact -- `phone`: Customer phone number for contact -- Other optional tags can be added with more details from the customer - -```jsonc -{ - "kind": 16, - "tags": [ - // Required tags - ["p", ""], - ["subject", ""], - ["type", "1"], // Order creation - ["order", ""], // Unique order identifier - ["amount", ""], - - // Order items (can repeat) - ["item", "30402::", ""], - - // Shipping details - ["shipping", "30406::"], - ["address", ""], - - // Customer contact - ["email", ""], // Optional - ["phone", ""], // Optional - ], - "content": "Order notes or special requests" -} -``` -#### 2. Payment Request -There are two variants depending on payment processing mode: manual or automatic processing. After the buyer pays the payment request, they MUST send a payment receipt to the merchant using a kind:`17` dm. - -##### Manual Processing (merchant → buyer) - -In this mode, the merchant manually initiates the payment by sending a payment request to the buyer. This requires either: -- The merchant being online to process requests, or -- Having an automated system for processing payment requests, which can be run by the merchant or a service they rely on according to merchant preferences. - -Important considerations: -- Merchant shouldn't have a recommended application in their merchant's preferences -- Final price may differ from the order creation time -- Merchants decide whether to honor original prices -- Buyers can cancel orders if they don't agree with price changes - -**Content:** (Optional) Human readable payment instructions and notes - -**Required tags:** -- `p`: Buyer's public key -- `subject`: Human-friendly subject line for order payment requests -- `type`: Must be "2" to indicate payment request -- `order`: The unique order identifier from the original order -- `amount`: Total payment amount in satoshis - -**Optional tags:** -- `payment`: Payment method details, can appear multiple times for different options: - - Lightning format: `["payment", "lightning", ""]` - - Bitcoin format: `["payment", "bitcoin", ""]` - - eCash format: `["payment", "ecash", ""]` -- `expiration`: Include if the payment format has a defined expiration time - -```jsonc -{ - "kind": 16, - "tags": [ - // Required tags - ["p", ""], - ["subject", "order-payment"], - ["type", "2"], // Payment request - ["order", ""], - ["amount", ""], - - // Payment options (can include multiple) - ["payment", "lightning", ""], - ["payment", "bitcoin", ""], - ["payment", "ecash", ""], - ["expiration", ""], - ], - "content": "Payment instructions and notes" -} -``` - -##### Automatic Processing (buyer → merchant) -In this mode, the merchant MUST set valid payment options in their kind:`0` event (such as `cashu` or `lud16`). The key difference is that the buyer initiates the payment request using information provided by the merchant. For merchants using `manual` payment preference, they SHOULD use [NIP-89](89.md) to specify their preferred payment processing service, which can then automatically handle payment requests on their behalf, as described in the merchant preferences section above. - -```jsonc -{ - "kind": 16, - "tags": [ - // Required tags - ["p", ""], - ["subject", "order-payment"], - ["type", "2"], // Payment request - ["order", ""], - ["amount", ""], - - // Payment details from service - ["payment", "lightning", ""], - ["payment", "bitcoin", ""], - ["payment", "ecash", ""], - ], - "content": "Service-generated payment details" -} -``` - -#### 3. Order Status Updates -Once the merchant receives payment, they MUST update the status to "confirmed". Status updates can be sent as soon as a new order is acknowledged, initially setting the status to "pending". The "pending" status is optional and can be skipped, starting directly with "confirmed" once payment is received. - -**Content:** (Optional) Human readable status update - -**Required tags:** -- `p`: Buyer's public key -- `subject`: Human-friendly subject line for status updates -- `type`: Must be "3" to indicate status update -- `order`: The original order identifier -- `status`: Current order status: - - `pending`: Order received but awaiting payment - - `confirmed`: Payment received and verified - - `processing`: Order is being prepared - - `completed`: Order fulfilled - - `cancelled`: Order cancelled by either party - -```jsonc -{ - "kind": 16, - "tags": [ - // Required tags - ["p", ""], - ["subject", "order-info"], - ["type", "3"], // Status update - ["order", ""], - - // Status information - ["status", ""], // pending|confirmed|processing|completed|cancelled - ], - "content": "Human readable status update" -} -``` - -Buyers may also send a status update to cancel an order, ideally before the status has been set to "confirmed": - -```jsonc -{ - "kind": 16, - "tags": [ - // Required tags - ["p", ""], - ["subject", "order-info"], - ["type", "3"], // Status update - ["order", ""], - - // Status information - ["status", ""], // cancelled - ], - "content": "Human readable status update" -} -``` - -#### 4. Shipping Updates -Sent by merchant to provide delivery tracking and status information. - -**Content:** (Optional) Human readable shipping status and tracking information - -**Required tags:** -- `p`: Buyer's public key -- `subject`: Human-friendly subject line for shipping updates -- `type`: Must be "4" to indicate shipping update -- `order`: The original order identifier -- `status`: Current shipping status: - - `processing`: Order is being prepared for shipping - - `shipped`: Package has been handed to carrier - - `delivered`: Successfully delivered to destination - - `exception`: Delivery issue or delay encountered - -**Optional tags:** -- `tracking`: Carrier's tracking number -- `carrier`: Name of shipping carrier -- `eta`: Expected delivery time as unix timestamp - -```jsonc -{ - "kind": 16, - "tags": [ - // Required tags - ["p", ""], - ["subject", "shipping-info"], - ["type", "4"], // Shipping update - ["order", ""], - - // Shipping details - ["status", ""], // processing|shipped|delivered|exception - ["tracking", ""], - ["carrier", ""], - ["eta", ""], - ], - "content": "Shipping status and tracking information" -} -``` - -#### 5. General Communication -Used for any order-related messages (Kind 14) - -```jsonc -{ - "kind": 14, - "tags": [ - // Required tags - ["p", ""], - ["subject", ""], // Optional, can be empty - ], - "content": "General communication message" -} -``` - -#### 6. Payment Receipt -Sent by buyer to confirm payment completion. The receipt can include proof of payment from any payment system, including traditional fiat gateways. - -**Content:** (Optional) Human readable payment confirmation details - -**Required tags:** -- `p`: Merchant's public key -- `subject`: Human-friendly subject line for order receipt -- `order`: The original order identifier -- `payment`: Payment proof details (at least one required): - - Generic format: `["payment", "", "", ""]` - - Common examples: - - Lightning: `["payment", "lightning", "", ""]` - - Bitcoin: `["payment", "bitcoin", "
", ""]` - - eCash: `["payment", "ecash", "", ""]` - - Fiat: `["payment", "fiat", "", ""]` -- `amount`: Payment amount - -```jsonc -{ - "kind": 17, - "tags": [ - // Required tags - ["p", ""], - ["subject", "order-receipt"], - ["order", ""], - - // Payment proof (one required) - ["payment", "", "", ""], - ["payment", "lightning", "", ""], - ["payment", "bitcoin", "
", ""], - ["payment", "ecash", "", ""], - ["payment", "fiat", "", ""], - - // Metadata - ["amount", ""] - ], - "content": "Payment confirmation details" -} -``` - -#### Notes -1. Message Flow: - - Receipts should include verifiable proofs - -2. Payment Processing: - - Manual mode provides more flexibility - - Automatic mode enables faster processing and convenience - - Multiple payment options can be offered - -3. Status Tracking: - - Use consistent status codes - - Include timestamps for all updates - - Provide clear user messages - -## 5. Product Reviews (Kind: 31555) - -Product reviews follow [NIP-85](https://github.com/nostr-protocol/nips/blob/b1432b705f553bde6c4eb5fcfde8525d2913b477/85.md) and [QTS](https://habla.news/u/arkinox@arkinox.tech/DLAfzJJpQDS4vj3wSleum) guidelines with additional marketplace-specific rating criteria. Reviews provide structured feedback about products, merchants, and the overall purchase experience. - -**Content:** Detailed review text - -**Required tags:** -- `d`: Reference to product `["d", "a:30402::"]` -- `rating`: Primary rating `["rating", "", "thumb"]` - - score: 0 (negative) to 1 (positive) - - "thumb" label MUST be present as primary rating - -**Optional tags:** -- Additional Ratings: - - `rating`: Category scores `["rating", "", ""]` - - score: 0 to 1 (supports fractional values) - - category: These are optional, some standard categories may include: - - "value": Price vs quality - - "quality": Product quality - - "delivery": Shipping experience - - "communication": Merchant responsiveness - -```jsonc -{ - "kind": 31555, - "created_at": , - "tags": [ - // Required tags - ["d", "a:30402::"], - ["rating", "1", "thumb"], // Primary rating - - // Optional rating categories - ["rating", "0.8", "value"], - ["rating", "1.0", "quality"], - ["rating", "0.6", "delivery"], - ["rating", "0.9", "communication"] - ], - "content": "Detailed review text" -} -``` - -#### Rating Calculation -The final score combines the primary "thumb" rating (50% weight) with additional category ratings (50% combined weight): - -``` -Total Score = (Thumb × 0.5) + (0.5 × (∑(Category Ratings) ÷ Number of Categories)) -``` - -#### Notes -1. Rating System: - - Primary thumb rating is required, it determines the overall an overall rating. - - Additional categories are optional - - Scores support fractional values between 0-1 - - Custom categories can be added - -## 6. Implementation Guidelines - -### Payment Flow Details - -#### Payment Preferences -Merchants can specify their payment preferences in their kind:`0` event using the `payment_preference` tag: -``` -["payment_preference", ""] -``` - -If not present, it defaults to `manual`. The preferences are processed in this order of complexity: -1. Manual (default): Merchant provides payment requests directly -2. eCash: Ideally the merchant has a kind `10019` event to know what mint they prefer. - - If the `10019` event is not present, payment can be made by sending the token embedded directly in the order receipt message from a previously set mint (whether default or user selected); otherwise, the merchant's preferred mint SHOULD be used. -3. Lightning: Requires `lud16` or related lightning fields in kind `0` - -#### Payment Processing Scenarios - -1. **Manual Processing** - - Merchant initiates payment request - - Used when no application is recommended or automatic preferences are set - - Merchant must manually send payment requests - - Buyer waits for merchant's payment instructions - - Merchants can have their own service that listens for new orders and then sends the payment request - -2. **Automatic Processing** - - Buyer initiates payment request - - Requires a valid `payment_preference` in merchant's kind `0` - - Service-Based Processing processing if `payment_preference` is `manual` and the merchant have a recommended application - - Supports automatic payments via: - - eCash tokens (locked to merchant's pubkey) - - Lightning (using merchant's `lud16` address) - -3. **Service-Based Processing** - - Merchant MUST set `payment_preference` to `manual` - - Merchant SHOULD have a [NIP-89](89.md) kind `31989` event recommending their preferred service - - Buyers can immediately request payment using the service - - Service handles payment details and completion monitoring - -For all scenarios: -- Buyer MUST send payment receipt after completion -- Message direction is determined by `p` tag -- Merchant's [NIP-89](89.md) application preferences SHOULD be respected - -### Marketplace Application Role -Marketplace applications can optionally facilitate the order processing and payment request by: - -1. Generating payment requests based on merchant preferences when buyers initiate orders -2. Verifying payments and generating receipts automatically by prompting the buyer to sign the event -3. Helping merchants managing inventory and order status updates -4. Coordinating shipping information -5. Price calculations - -This provides a smoother user experience while maintaining the ability for direct merchant-buyer communication as a fallback mechanism. - -### Notes and Considerations - -1. Tags are used for all structured, machine-readable data to facilitate easier parsing and filtering. - -2. The content field is reserved for human-readable messages and additional information that doesn't require machine parsing. - -3. All timestamps should be in Unix format (seconds since epoch). - -4. Order IDs should be used consistently across all related messages. - -5. Message threading should follow [NIP-10](10.md) conventions when replies are needed. +Read [AGENTS.md](AGENTS.md) before making structural or semantic changes. Structural PRs should preserve implementation-sensitive text and keep semantic changes in separate, explicit proposals. diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 0000000..2ba8eba --- /dev/null +++ b/SPEC.md @@ -0,0 +1,837 @@ +Marketplace Protocol +--------------------------- + +`draft` + +A protocol specification for decentralized marketplaces on Nostr that provides an interoperable, full-featured e-commerce framework. + +## Table of Contents +1. Protocol Requirements +2. Core Protocol Components +3. Events and Kinds +4. Order Communication Flow and Payment Processing +5. Product Reviews +6. Implementation Guidelines + +## 1. Protocol Requirements + +The protocol defines both required core components and optional features to support diverse marketplace needs. + +### Required Components +Implementations MUST support the following core features: + +- Product listing events (Kind: 30402) +- Product collection events (Kind: 30405) for product-to-collection references +- Merchant's preferences +- Order communication and processing via [NIP-17](17.md) encrypted messages + +### Optional Components +These features MAY be implemented based on specific marketplace needs: + +- Extended product metadata +- Shipping options (Kind: 30406) +- Product collections (Kind: 30405) +- Drafts following [NIP-37](37.md) +- Product reviews (Kind: 31555) +- Service assisted order and payment processing + +#### Watch-only clients +Watch-only clients are applications that allow users to display products without implementing full e-commerce capabilities. These clients don't need to support all required components - product rendering alone can be sufficient. However, ideally, they should also handle logic for looking up collections, reviews, and shipping options. Support for order communication using [NIP-17](17.md) is optional. + +## 2. Core Protocol Components + +### Core Flows +1. Merchant Preferences + - Application preferences via [NIP-89](89.md) + - Payment method preferences via kind `0` tags + +2. Order Processing + - Encrypted buyer-seller communication + - Status updates and confirmations + +3. Shipping + - Option definition and pricing + - Geographic restrictions + +4. Payment + - Multiple payment methods + - Verification and receipts + +Standard e-commerce flow: +1. Product discovery +2. Cart addition +3. Merchant preference verification +4. Shipping calculation +5. Payment processing +6. Order confirmation +7. Encrypted message follow-up + +### Merchant Preferences +Merchants MAY specify preferences for how they want users to interact with them, including which applications to use and payment methods to accept. These preferences ensure a consistent experience and streamline operations. Merchants indicate their preferences through two mechanisms: + +1. Application Preferences ([NIP-89](89.md)): +- The recommended application MUST publish a kind `31990` event +- The merchant MUST publish a kind `31989` event recommending that application + +2. Payment Preferences: +- Set via `payment_preference` tag in the merchant's kind `0` event +- Valid values: `manual | ecash | lud16` +- Defaults to `manual` if not specified + +Applications implementing this NIP MUST handle preferences as follows: + +1. When `payment_preference` is `manual`: +- If merchant recommends an app: MUST direct users to that app +- If no app recommendation: Use traditional interactive flow (buyer places order and waits for merchant's payment request) + +2. When `payment_preference` is `ecash` or `lud16`: +- If merchant recommends an app: SHOULD direct users there first, but they MAY also offer to continue if compatible with the payment preference +- If no recommendations: Use specified payment method directly + +3. When no preferences are set: +- Use traditional interactive flow + - Buyer sends order + - Wait for merchant's payment request + +Buyers can verify merchant preferences by: +- Checking kind `31990` events for recommended applications +- Checking kind `0` events for payment preferences + +This verification helps buyers follow merchant-approved paths and avoid potential scams or poor experiences. + +## 3. Events and Kinds + +### Product Listing (Kind: 30402) + +Products are the core element in a marketplace. Each product listing MUST contain basic metadata and MAY contain additional details. Their configuration is the source of truth, overriding other possible configurations of other market elements such as collections, no configuration is cascaded to products, they MUST explicitly reference an attribute to inherit it. + +**Content**: Product description, markdown is allowed +**Required tags**: +- `d`: Unique product identifier for referencing the listing +- `title`: Product name/title for display +- `price`: Price information array `[, , ]` + - amount: Decimal number (e.g., "10.99") + - currency: ISO 4217 code (e.g., "USD", "EUR") + - frequency: Optional subscription interval using ISO 8601 duration units (e.g. 'D' for daily, 'W' for weekly, 'Y' for yearly). + +**Optional tags**: +- Product Details: + - `type`: Product classification `[, ]` + - type: "simple", "variable", or "variation" + - format: "digital" or "physical" + - Default/if not present: type: "simple", format: "digital" + - `visibility`: Display status ("hidden", "on-sale", "pre-order"). Default/if not present: "on-sale" + - `stock`: Available quantity as integer + - `summary`: Short product description + - `spec`: Product specifications `[, ]`, can appear multiple times + +- Media: + - `image`: Product images `[, , ]`, MAY appear multiple times + - url: Direct image URL + - dimensions: Optional, in pixels, "x" format, if not present the place in the array should be respected by using an empty string `""` + - sorting order: Optional integer for order sorting. Values are sorted from lowest to highest, independent of starting value (not restricted to start with 0 or 1) + +- Physical Properties: + - `weight`: Product weight `[, ]` using ISO 80000-1 + - `dim`: Dimensions `[xx, ]` using ISO 80000-1 + +- Location: + - `location`: Human-readable location string or collection coordinates + - `g`: Geohash for precise location lookup or collection coordinates + +- Organization: + - `t`: Product categories/tags, MAY appear multiple times + - `a`: Product reference "30402::", MUST appear only once to reference parent products in a variable/variation configuration + - `a`: Collection reference "30405::", MAY appear multiple times + - `shipping_option`: Shipping options, MAY appear multiple times + - Format: "30406::" for direct options + - Format: "30405::" for collection shipping + - `extra-cost`: Optional third element in the array, to add extra cost (in the product's currency) for the shipping method. In case of reference a collection the extra cost should be applied to all shipping options from the collection. + +```jsonc +{ + "kind": 30402, + "created_at": , + "content": "", + "tags": [ + // Required tags + ["d", ""], + ["title", ""], + ["price", "", "", ""], + + // Product details + ["type", "", ""], // Defaults: simple, digital + ["visibility", ""], // Default: on-sale + ["stock", ""], // Available quantity + ["summary", ""], + + // Media and specs + ["image", "", "", ""], + ["spec", "", ""], // Product specifications (e.g., "screen-size", "21 inch"). MAY appear multiple times + + // Physical properties (for shipping) + ["weight", "", ""], // ISO 80000-1 units (g, kg, etc) + ["dim", "xx", ""], // ISO 80000-1 units (mm, cm, m) + + // Location + ["location", "
"], + ["g", ""], + + // Classifications + ["t", ""], + + // References + ["shipping_option", "<30406|30405>::", ""], // Shipping options or collection, MAY appear multiple times + ["a", "30405::"] // Product collection + ] +} +``` + +#### Notes +1. Product Configuration: + - Products can be simple, variable (with options), or variations of variable products + - Digital products skip shipping requirements + - Visibility controls product display status + +2. Variable products: + - The parent or "root" product should use `variable` as value for `type` + - The variations of the parent product should use `variation` as value for `type`. + - Variations MUST include an `a` tag pointing to the `variable` parent product. + +2. Shipping Rules: + - Shipping options can be defined directly by pointing to a shipping event, or inherited from collections + - If the product specifies product-specific shipping, and also from a collection, shipping options MUST be merged. + +3. Collections and Categories: + - Products can refer to one o multiple collections using `a` tags, whether or not they are part of it, for discoverability purposes. + - Categories ("t" tags) aid in discovery and organization + +4. Location Support: + - Optional location data aids in local marketplace features, they can point to a collection event to inherit it's value + - Geohash enables precise location-based searches, they can point to a collection event to inherit it's value + +### Product Collection (Kind: 30405) +A specialized event type using [NIP-51](51.md) like list format to organize related products into groups. Collections allow merchants or any user to create meaningful product groupings and share common attributes that products can also reference, establishing one-to-many relationships. + +**Content**: Optional collection description + +**Required tags**: +- `d`: Unique collection identifier +- `title`: Collection display name/title +- `a`: Product references `["a", "30402::"]` + - Multiple product references allowed + - References must point to valid product listings + +**Optional tags**: +- Display: + - `image`: Collection banner/thumbnail URL + - `summary`: Brief collection description + +- Location: + - `location`: Human-readable location string + - `g`: Geohash for precise location lookup + +- Reference Options: + - `shipping_option`: Available shipping options `["shipping_option", "30406::"]`, MAY appear multiple times + +```jsonc +{ + "kind": 30405, + "created_at": , + "content": "", + "tags": [ + // Required tags + ["d", ""], + ["title", ""], + ["a", "30402::"], // Product reference + + // Optional tags + ["image", ""], + ["summary", ""], + + // Location + ["location", ""], + ["g", ""], + + // Reference Options + ["shipping_option", "30406::"], // Available shipping options, MAY appear multiple times + ] +} +``` + +#### Notes +1. Collection Management: + - Collections can contain any number of products + - Products can belong to multiple collections + +2. Reference Model: + - Collection settings (shipping, location, geohash) serve as references only + - Products MUST explicitly reference collection resources to inherit collection attributes (e.g. shipping, location, geohash). + - No automatic cascading of settings to products + +3. Location Support: + - Optional location data helps with marketplace organization + - Enables geographic grouping of related products + +### Drafts +Products and collections can be saved as private drafts while being prepared for publication. This allows merchants to work on listings before making them publicly visible. Implementation MUST follow [NIP-37](https://github.com/nostr-protocol/nips/blob/master/37.md) for draft management. + +### Shipping Option (Kind: 30406) +A specialized event type for defining shipping methods, costs, and constraints. Shipping options can be published by merchants or third-party providers (delivery companies, DVMs, etc.) and referenced by product listings or collections. + +**Content**: Optional human-friendly shipping description + +**Required tags**: +- `d`: Unique shipping option identifier +- `title`: Display title for the shipping method +- `price`: Base cost array `[, ]` +- `country`: Array of ISO 3166-1 alpha-2 country codes `[, , ...]` +- `service`: Service type ("standard", "express", "overnight", "pickup") + +**Optional tags**: +- Extra details: + - `carrier`: The name of the carrier that will be used for the delivery +- Time and Location: + - `region`: Array of ISO 3166-2 region codes for which shipping method is available `[, , ...]` + - `duration`: Delivery window `[, , ]` using ISO 8601 duration units + - min: Minimum delivery time + - max: Maximum delivery time + - unit: "H" (hours), "D" (days), "W" (weeks) + - `location`: Physical address for pickup + - `g`: Geohash for precise location + +- Constraints: + - `weight-min`: Minimum weight `[, ]` (ISO 80000-1) + - `weight-max`: Maximum weight `[, ]` + - `dim-min`: Minimum dimensions `[xx, ]` + - `dim-max`: Maximum dimensions `[xx, ]` + +- Price Calculations: + - `price-weight`: Per weight pricing `[, ]` + - `price-volume`: Per volume pricing `[, ]` + - `price-distance`: Per distance pricing `[, ]` + +```jsonc +{ + "kind": 30406, + "created_at": , + "content": "", + "tags": [ + // Required tags + ["d", ""], + ["title", ""], + ["price", "", ""], + ["country", "", "...", "..."], // Array of country codes + ["service", ""], + + // Extra details + ["carrier",""] + + // Time and Location + ["region", "", "...", "..."], // Array of region codes + ["duration", "", "", ""], // ISO 8601 duration units (H/D/W) + ["location", "
"], + ["g", ""], + + // Constraints + ["weight-min", "", ""], + ["weight-max", "", ""], + ["dim-min", "xx", ""], + ["dim-max", "xx", ""], + + // Price Calculations + ["price-weight", "", ""], + ["price-volume", "", ""], + ["price-distance", "", ""] + ] +} +``` + +#### Implementation Examples + +Local Pickup: +```jsonc +{ + "kind": 30406, + "created_at": 1703187600, + "content": "Downtown Store Pickup", + "tags": [ + ["d", "downtown-pickup"], + ["title", "Downtown Store Pickup"], + ["price", "0", "USD"], + ["country", "US"], + ["region", "US-FL"], + ["service", "pickup"], + ["location", "123 Main St, Downtown, FL"], + ["g", "dhwm9c4ws"] + ] +} +``` + +Standard Shipping: +```jsonc +{ + "kind": 30406, + "created_at": 1703187600, + "content": "Standard Regional Shipping", + "tags": [ + ["d", "standard-regional"], + ["title", "Standard Shipping"], + ["price", "5.99", "USD"], + ["country", "US"], + ["region", "US-FL"], + ["service", "standard"], + ["duration", "24", "72", "H"], // 24-72 hours delivery window + ["weight-max", "30", "kg"], + ["dim-max", "120x60x60", "cm"], + ["price-weight", "0.75", "USD", "kg"] + ] +} +``` + +#### Notes +1. Event Management: + - Create separate events for each distinct shipping option + - Each option needs a unique `d` tag identifier + - Merchants can reference third-party shipping options + +2. Shipping Rules: + - Physical pickup requires location and/or geohash + - Weight/dimension constraints use ISO 80000-1 units + +3. Client Behavior: + - Group options by service type and location + - Use geohash for distance-based sorting + - Validate package constraints before offering options + +## 4. Order Communication Flow and Payment Processing + +Order processing and status updates use [NIP-17](17.md) encrypted direct messages, with three event kinds serving different purposes: + +- Kind `14`: Regular communication between parties + - General inquiries and responses + - Order clarifications + - Subject can be order ID or empty + +- Kind `16`: Order processing and status. These messages include a `type` field that indicates the specific kind of message + - Order creation and details. `type`: 1 + - Payment requests. `type`: 2 + - Status updates. `type`: 3 + - Shipping information. `type`: 4 + +- Kind `17`: Payment receipts and verification + +Message direction is determined by the author, and `p` tag: +- Buyer → Merchant: event author is the buyer, `p` tag contains merchant's pubkey +- Merchant → Buyer: event author is the merchant, `p` tag contains buyer's pubkey + +The payment request flow can operate in two modes: +1. Direct: Merchant processes requests manually. Payment request is initiated by the merchant +2. Service-assisted: Merchant's payment service handles requests. Payment request is initiated by the buyer + +### Message Types +#### 1. Order Creation +Sent by buyer to initiate order process. + +**Content:** (Optional) Human readable order notes or special requests + +**Required tags:** +- `p`: Merchant's public key +- `subject`: Human-friendly subject line for order information +- `type`: Must be "1" to indicate order creation +- `order`: Unique identifier for the order +- `amount`: Total order amount in satoshis +- `item`: Product reference in format "30402::" with quantity. MAY appear multiple times + +**Optional tags:** +- `shipping`: Reference to shipping option "30406::" +- `address`: Shipping address details +- `email`: Customer email for contact +- `phone`: Customer phone number for contact +- Other optional tags can be added with more details from the customer + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", ""], + ["type", "1"], // Order creation + ["order", ""], // Unique order identifier + ["amount", ""], + + // Order items (can repeat) + ["item", "30402::", ""], + + // Shipping details + ["shipping", "30406::"], + ["address", ""], + + // Customer contact + ["email", ""], // Optional + ["phone", ""], // Optional + ], + "content": "Order notes or special requests" +} +``` +#### 2. Payment Request +There are two variants depending on payment processing mode: manual or automatic processing. After the buyer pays the payment request, they MUST send a payment receipt to the merchant using a kind:`17` dm. + +##### Manual Processing (merchant → buyer) + +In this mode, the merchant manually initiates the payment by sending a payment request to the buyer. This requires either: +- The merchant being online to process requests, or +- Having an automated system for processing payment requests, which can be run by the merchant or a service they rely on according to merchant preferences. + +Important considerations: +- Merchant shouldn't have a recommended application in their merchant's preferences +- Final price may differ from the order creation time +- Merchants decide whether to honor original prices +- Buyers can cancel orders if they don't agree with price changes + +**Content:** (Optional) Human readable payment instructions and notes + +**Required tags:** +- `p`: Buyer's public key +- `subject`: Human-friendly subject line for order payment requests +- `type`: Must be "2" to indicate payment request +- `order`: The unique order identifier from the original order +- `amount`: Total payment amount in satoshis + +**Optional tags:** +- `payment`: Payment method details, can appear multiple times for different options: + - Lightning format: `["payment", "lightning", ""]` + - Bitcoin format: `["payment", "bitcoin", ""]` + - eCash format: `["payment", "ecash", ""]` +- `expiration`: Include if the payment format has a defined expiration time + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-payment"], + ["type", "2"], // Payment request + ["order", ""], + ["amount", ""], + + // Payment options (can include multiple) + ["payment", "lightning", ""], + ["payment", "bitcoin", ""], + ["payment", "ecash", ""], + ["expiration", ""], + ], + "content": "Payment instructions and notes" +} +``` + +##### Automatic Processing (buyer → merchant) +In this mode, the merchant MUST set valid payment options in their kind:`0` event (such as `cashu` or `lud16`). The key difference is that the buyer initiates the payment request using information provided by the merchant. For merchants using `manual` payment preference, they SHOULD use [NIP-89](89.md) to specify their preferred payment processing service, which can then automatically handle payment requests on their behalf, as described in the merchant preferences section above. + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-payment"], + ["type", "2"], // Payment request + ["order", ""], + ["amount", ""], + + // Payment details from service + ["payment", "lightning", ""], + ["payment", "bitcoin", ""], + ["payment", "ecash", ""], + ], + "content": "Service-generated payment details" +} +``` + +#### 3. Order Status Updates +Once the merchant receives payment, they MUST update the status to "confirmed". Status updates can be sent as soon as a new order is acknowledged, initially setting the status to "pending". The "pending" status is optional and can be skipped, starting directly with "confirmed" once payment is received. + +**Content:** (Optional) Human readable status update + +**Required tags:** +- `p`: Buyer's public key +- `subject`: Human-friendly subject line for status updates +- `type`: Must be "3" to indicate status update +- `order`: The original order identifier +- `status`: Current order status: + - `pending`: Order received but awaiting payment + - `confirmed`: Payment received and verified + - `processing`: Order is being prepared + - `completed`: Order fulfilled + - `cancelled`: Order cancelled by either party + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-info"], + ["type", "3"], // Status update + ["order", ""], + + // Status information + ["status", ""], // pending|confirmed|processing|completed|cancelled + ], + "content": "Human readable status update" +} +``` + +Buyers may also send a status update to cancel an order, ideally before the status has been set to "confirmed": + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-info"], + ["type", "3"], // Status update + ["order", ""], + + // Status information + ["status", ""], // cancelled + ], + "content": "Human readable status update" +} +``` + +#### 4. Shipping Updates +Sent by merchant to provide delivery tracking and status information. + +**Content:** (Optional) Human readable shipping status and tracking information + +**Required tags:** +- `p`: Buyer's public key +- `subject`: Human-friendly subject line for shipping updates +- `type`: Must be "4" to indicate shipping update +- `order`: The original order identifier +- `status`: Current shipping status: + - `processing`: Order is being prepared for shipping + - `shipped`: Package has been handed to carrier + - `delivered`: Successfully delivered to destination + - `exception`: Delivery issue or delay encountered + +**Optional tags:** +- `tracking`: Carrier's tracking number +- `carrier`: Name of shipping carrier +- `eta`: Expected delivery time as unix timestamp + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "shipping-info"], + ["type", "4"], // Shipping update + ["order", ""], + + // Shipping details + ["status", ""], // processing|shipped|delivered|exception + ["tracking", ""], + ["carrier", ""], + ["eta", ""], + ], + "content": "Shipping status and tracking information" +} +``` + +#### 5. General Communication +Used for any order-related messages (Kind 14) + +```jsonc +{ + "kind": 14, + "tags": [ + // Required tags + ["p", ""], + ["subject", ""], // Optional, can be empty + ], + "content": "General communication message" +} +``` + +#### 6. Payment Receipt +Sent by buyer to confirm payment completion. The receipt can include proof of payment from any payment system, including traditional fiat gateways. + +**Content:** (Optional) Human readable payment confirmation details + +**Required tags:** +- `p`: Merchant's public key +- `subject`: Human-friendly subject line for order receipt +- `order`: The original order identifier +- `payment`: Payment proof details (at least one required): + - Generic format: `["payment", "", "", ""]` + - Common examples: + - Lightning: `["payment", "lightning", "", ""]` + - Bitcoin: `["payment", "bitcoin", "
", ""]` + - eCash: `["payment", "ecash", "", ""]` + - Fiat: `["payment", "fiat", "", ""]` +- `amount`: Payment amount + +```jsonc +{ + "kind": 17, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-receipt"], + ["order", ""], + + // Payment proof (one required) + ["payment", "", "", ""], + ["payment", "lightning", "", ""], + ["payment", "bitcoin", "
", ""], + ["payment", "ecash", "", ""], + ["payment", "fiat", "", ""], + + // Metadata + ["amount", ""] + ], + "content": "Payment confirmation details" +} +``` + +#### Notes +1. Message Flow: + - Receipts should include verifiable proofs + +2. Payment Processing: + - Manual mode provides more flexibility + - Automatic mode enables faster processing and convenience + - Multiple payment options can be offered + +3. Status Tracking: + - Use consistent status codes + - Include timestamps for all updates + - Provide clear user messages + +## 5. Product Reviews (Kind: 31555) + +Product reviews follow [NIP-85](https://github.com/nostr-protocol/nips/blob/b1432b705f553bde6c4eb5fcfde8525d2913b477/85.md) and [QTS](https://habla.news/u/arkinox@arkinox.tech/DLAfzJJpQDS4vj3wSleum) guidelines with additional marketplace-specific rating criteria. Reviews provide structured feedback about products, merchants, and the overall purchase experience. + +**Content:** Detailed review text + +**Required tags:** +- `d`: Reference to product `["d", "a:30402::"]` +- `rating`: Primary rating `["rating", "", "thumb"]` + - score: 0 (negative) to 1 (positive) + - "thumb" label MUST be present as primary rating + +**Optional tags:** +- Additional Ratings: + - `rating`: Category scores `["rating", "", ""]` + - score: 0 to 1 (supports fractional values) + - category: These are optional, some standard categories may include: + - "value": Price vs quality + - "quality": Product quality + - "delivery": Shipping experience + - "communication": Merchant responsiveness + +```jsonc +{ + "kind": 31555, + "created_at": , + "tags": [ + // Required tags + ["d", "a:30402::"], + ["rating", "1", "thumb"], // Primary rating + + // Optional rating categories + ["rating", "0.8", "value"], + ["rating", "1.0", "quality"], + ["rating", "0.6", "delivery"], + ["rating", "0.9", "communication"] + ], + "content": "Detailed review text" +} +``` + +#### Rating Calculation +The final score combines the primary "thumb" rating (50% weight) with additional category ratings (50% combined weight): + +``` +Total Score = (Thumb × 0.5) + (0.5 × (∑(Category Ratings) ÷ Number of Categories)) +``` + +#### Notes +1. Rating System: + - Primary thumb rating is required, it determines the overall an overall rating. + - Additional categories are optional + - Scores support fractional values between 0-1 + - Custom categories can be added + +## 6. Implementation Guidelines + +### Payment Flow Details + +#### Payment Preferences +Merchants can specify their payment preferences in their kind:`0` event using the `payment_preference` tag: +``` +["payment_preference", ""] +``` + +If not present, it defaults to `manual`. The preferences are processed in this order of complexity: +1. Manual (default): Merchant provides payment requests directly +2. eCash: Ideally the merchant has a kind `10019` event to know what mint they prefer. + - If the `10019` event is not present, payment can be made by sending the token embedded directly in the order receipt message from a previously set mint (whether default or user selected); otherwise, the merchant's preferred mint SHOULD be used. +3. Lightning: Requires `lud16` or related lightning fields in kind `0` + +#### Payment Processing Scenarios + +1. **Manual Processing** + - Merchant initiates payment request + - Used when no application is recommended or automatic preferences are set + - Merchant must manually send payment requests + - Buyer waits for merchant's payment instructions + - Merchants can have their own service that listens for new orders and then sends the payment request + +2. **Automatic Processing** + - Buyer initiates payment request + - Requires a valid `payment_preference` in merchant's kind `0` + - Service-Based Processing processing if `payment_preference` is `manual` and the merchant have a recommended application + - Supports automatic payments via: + - eCash tokens (locked to merchant's pubkey) + - Lightning (using merchant's `lud16` address) + +3. **Service-Based Processing** + - Merchant MUST set `payment_preference` to `manual` + - Merchant SHOULD have a [NIP-89](89.md) kind `31989` event recommending their preferred service + - Buyers can immediately request payment using the service + - Service handles payment details and completion monitoring + +For all scenarios: +- Buyer MUST send payment receipt after completion +- Message direction is determined by `p` tag +- Merchant's [NIP-89](89.md) application preferences SHOULD be respected + +### Marketplace Application Role +Marketplace applications can optionally facilitate the order processing and payment request by: + +1. Generating payment requests based on merchant preferences when buyers initiate orders +2. Verifying payments and generating receipts automatically by prompting the buyer to sign the event +3. Helping merchants managing inventory and order status updates +4. Coordinating shipping information +5. Price calculations + +This provides a smoother user experience while maintaining the ability for direct merchant-buyer communication as a fallback mechanism. + +### Notes and Considerations + +1. Tags are used for all structured, machine-readable data to facilitate easier parsing and filtering. + +2. The content field is reserved for human-readable messages and additional information that doesn't require machine parsing. + +3. All timestamps should be in Unix format (seconds since epoch). + +4. Order IDs should be used consistently across all related messages. + +5. Message threading should follow [NIP-10](10.md) conventions when replies are needed. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..b4a45b4 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,81 @@ +# Architecture + +Status: explanatory map plus unchanged current core protocol text. + +Open Markets is organized around four homes for existing and future work: items, orders, payments, and delivery. This document is a navigation layer. It does not redefine the protocol; [../SPEC.md](../SPEC.md) remains the contiguous compatibility snapshot. + +## Pillar Map + +- Items: listings, collections, drafts, reviews, product metadata, discovery, categorization, and pricing. +- Orders: order creation, buyer/seller intent, status transitions, cancellation, and order-linked communication. +- Payments: merchant preferences, payment requests, payment receipts, payment proofs, and future payment rails. +- Delivery: shipping options, pickup, shipping updates, and future fulfillment models. + +## 2. Core Protocol Components + +### Core Flows +1. Merchant Preferences + - Application preferences via [NIP-89](89.md) + - Payment method preferences via kind `0` tags + +2. Order Processing + - Encrypted buyer-seller communication + - Status updates and confirmations + +3. Shipping + - Option definition and pricing + - Geographic restrictions + +4. Payment + - Multiple payment methods + - Verification and receipts + +Standard e-commerce flow: +1. Product discovery +2. Cart addition +3. Merchant preference verification +4. Shipping calculation +5. Payment processing +6. Order confirmation +7. Encrypted message follow-up + +### Merchant Preferences +Merchants MAY specify preferences for how they want users to interact with them, including which applications to use and payment methods to accept. These preferences ensure a consistent experience and streamline operations. Merchants indicate their preferences through two mechanisms: + +1. Application Preferences ([NIP-89](89.md)): +- The recommended application MUST publish a kind `31990` event +- The merchant MUST publish a kind `31989` event recommending that application + +2. Payment Preferences: +- Set via `payment_preference` tag in the merchant's kind `0` event +- Valid values: `manual | ecash | lud16` +- Defaults to `manual` if not specified + +Applications implementing this NIP MUST handle preferences as follows: + +1. When `payment_preference` is `manual`: +- If merchant recommends an app: MUST direct users to that app +- If no app recommendation: Use traditional interactive flow (buyer places order and waits for merchant's payment request) + +2. When `payment_preference` is `ecash` or `lud16`: +- If merchant recommends an app: SHOULD direct users there first, but they MAY also offer to continue if compatible with the payment preference +- If no recommendations: Use specified payment method directly + +3. When no preferences are set: +- Use traditional interactive flow + - Buyer sends order + - Wait for merchant's payment request + +Buyers can verify merchant preferences by: +- Checking kind `31990` events for recommended applications +- Checking kind `0` events for payment preferences + +This verification helps buyers follow merchant-approved paths and avoid potential scams or poor experiences. + +## Navigation + +- Item event material is transposed into [../pillars/items.md](../pillars/items.md). +- Order communication material is transposed into [../pillars/orders.md](../pillars/orders.md). +- Payment preference and receipt material is transposed into [../pillars/payments.md](../pillars/payments.md). +- Shipping and fulfillment material is transposed into [../pillars/delivery.md](../pillars/delivery.md). +- The current e-commerce lane is preserved in [../lanes/ecommerce.md](../lanes/ecommerce.md). diff --git a/docs/compatibility.md b/docs/compatibility.md new file mode 100644 index 0000000..356e9ff --- /dev/null +++ b/docs/compatibility.md @@ -0,0 +1,101 @@ +# Compatibility + +Status: explanatory guardrail for current normative material. + +The current protocol behavior is preserved by [../SPEC.md](../SPEC.md). Split pillar and lane files are navigation/transposition views over the same current material. + +## Compatibility Promise + +Existing applications should be able to keep using the current specification without modification. + +This structural refactor must not change: + +- event kind numbers +- tag names +- tag array shapes +- field names +- JSON examples +- required/optional semantics +- order of tags shown in examples where implementers may have copied them +- status values +- `type` values +- payment preference values +- payment proof shapes +- merchant preference behavior +- NIP-17 order communication assumptions +- NIP-99 listing compatibility +- MUST, SHOULD, and MAY requirements + +## Current Normative Inventory + +Event kinds and kind references currently present: + +- `30402`: Product Listing +- `30405`: Product Collection +- `30406`: Shipping Option +- `14`: Regular communication between parties +- `16`: Order processing and status +- `17`: Payment receipts and verification +- `31555`: Product Reviews +- `31989`: Merchant application recommendation +- `31990`: Recommended application event +- kind `0`: merchant profile payment preferences +- kind `10019`: preferred mint reference + +Implementation-sensitive tag and field names include: + +- `d` +- `title` +- `price` +- `type` +- `visibility` +- `stock` +- `summary` +- `spec` +- `image` +- `weight` +- `dim` +- `location` +- `g` +- `t` +- `a` +- `shipping_option` +- `p` +- `subject` +- `order` +- `amount` +- `item` +- `shipping` +- `address` +- `email` +- `phone` +- `payment` +- `expiration` +- `status` +- `tracking` +- `carrier` +- `eta` +- `rating` +- `payment_preference` + +## Compatibility Checks For PRs + +Before merging structural changes: + +1. Compare [../SPEC.md](../SPEC.md) with the pre-refactor README snapshot. +2. Inventory all kind numbers before and after. +3. Inventory all tag names before and after. +4. Inventory all MUST, SHOULD, and MAY statements before and after. +5. Compare JSON examples against [../SPEC.md](../SPEC.md). +6. Confirm external links are exact. +7. Confirm escrow/proposal material is not presented as current normative behavior. + +## Known Issues Not Fixed By This Refactor + +The inherited text has issues that may deserve later cleanup, but this refactor intentionally does not fix them: + +- relative NIP links such as `17.md`, `51.md`, `89.md`, and `10.md` +- duplicated note numbering +- minor grammar and spelling issues +- history mentioning `expires` while current text uses `expiration` +- lack of separate contribution and proposal workflow before this PR diff --git a/docs/history.md b/docs/history.md new file mode 100644 index 0000000..de92742 --- /dev/null +++ b/docs/history.md @@ -0,0 +1,33 @@ +# History and Prior Work + +Status: historical and explanatory. + +Open Markets builds on existing Nostr commerce work. This page acknowledges that history and provides exact links for contributors who need context. It does not replace, supersede, or reinterpret external specifications. + +## Current Source Lineage + +- The current Open Markets specification is preserved in [../SPEC.md](../SPEC.md). +- The current text is byte-identical to [Gamma Markets market-spec](https://github.com/GammaMarkets/market-spec) `spec.md`. +- The Gamma Markets repository remains the ancestor/current source for the inherited e-commerce marketplace specification. + +## Standards Context + +- [NIP-99 classified listings](https://github.com/nostr-protocol/nips/blob/master/99.md) is the current coordination point for listing primitives used by Nostr commerce clients. +- [NIP-15 marketplace](https://github.com/nostr-protocol/nips/blob/master/15.md) is important historical marketplace work and should be acknowledged respectfully when explaining the design space. + +## Related Builders and Implementations + +The Open Markets design space has been shaped by independent builders and projects including Gamma Markets, Shopstr, Plebeian, Conduit, Colabonate, Switchboard, and other Nostr commerce contributors. + +This repository should use language such as "builds on", "preserves", "transposes", "organizes", "acknowledges", "creates room for", and "maintains compatibility with". + +Avoid language such as "replaces", "fixes", "supersedes", "better than", or "the correct way" unless an upstream standard has already made that status explicit. + +## Proposal and Integration Context + +- [nostr-commerce-skill](https://github.com/welliv/nostr-commerce-skill) is an informational agent-friendly reference for commerce scenarios. +- [Colabonate NIP-115 draft](https://github.com/Colabonate/nips/blob/colabonate-freedom-protocol/115.md) and [nostr-protocol/nips PR 2323](https://github.com/nostr-protocol/nips/pull/2323) are active checkout, escrow, and dispute proposal context. +- [Pontmore PIP-00 agent definition](https://github.com/pontmore/protocol/blob/main/PIP-00-agent-definition.md) is experimental agent-related protocol work. +- [Switchboard escrow architecture](https://github.com/samuelralak/switchboard/blob/master/docs/escrow-architecture.md) is an implementation/informational escrow architecture reference. + +These references should be linked exactly and given room to develop. They should not be paraphrased into Open Markets normative requirements without a future explicit proposal. diff --git a/docs/refactor-plan.md b/docs/refactor-plan.md new file mode 100644 index 0000000..4fed659 --- /dev/null +++ b/docs/refactor-plan.md @@ -0,0 +1,263 @@ +# Open Markets Specification Refactor Plan + +Status: planning document for a structural reorganization PR. + +This plan describes how to make the repository easier to navigate, easier to contribute to, and easier to extend while preserving full backward compatibility with the current specification. The refactor is a transposition, not a recomposition. + +## 1. Current Repo Audit + +Current structure: + +```text +/ + README.md + LICENSE +``` + +Current state: + +- The current root `README.md` is byte-identical to `GammaMarkets/market-spec` `spec.md`. +- The repo has no separate compatibility, history, contribution, examples, or proposal workspace documents. +- The existing specification is framed primarily as a full-featured e-commerce framework. +- The current e-commerce lane is the only fully expressed lane and must remain clear. + +Current implementation-sensitive surface: + +- Event kinds: `30402`, `30405`, `30406`, `14`, `16`, `17`, `31555`, `31989`, `31990`, kind `0`, and kind `10019` references. +- Tags and fields include `d`, `title`, `price`, `type`, `visibility`, `stock`, `summary`, `spec`, `image`, `weight`, `dim`, `location`, `g`, `t`, `a`, `shipping_option`, `p`, `subject`, `order`, `amount`, `item`, `shipping`, `address`, `email`, `phone`, `payment`, `expiration`, `status`, `tracking`, `carrier`, `eta`, `rating`, and `payment_preference`. +- Required/optional language, status values, payment preference values, and JSON examples are implementation-sensitive. + +Known gaps to note but not fix in this PR: + +- Relative NIP links such as `17.md`, `51.md`, `89.md`, and `10.md` are inherited from the current text. +- Some notes are numbered inconsistently. +- Minor grammar and typo issues exist. +- History includes an `expires` commit note while current text uses `expiration`. +- There is no current distinction between normative, explanatory, historical, and experimental material. + +## 2. Prior Art Summary + +Reference these exactly. Do not absorb or rewrite their specs. + +| Reference | Role | Contribution | Reorganized location | +| --- | --- | --- | --- | +| [Gamma Markets market-spec](https://github.com/GammaMarkets/market-spec) | Normative ancestor/current source | Provides the current e-commerce marketplace spec text preserved in this repository. | `docs/history.md`, `docs/compatibility.md`, `SPEC.md` | +| [NIP-99 classified listings](https://github.com/nostr-protocol/nips/blob/master/99.md) | Current upstream coordination point | Provides the current base listing primitive for Nostr commerce coordination. | `README.md`, `docs/architecture.md`, `pillars/items.md` | +| [NIP-15 marketplace](https://github.com/nostr-protocol/nips/blob/master/15.md) | Historical | Important earlier marketplace work in the Nostr commerce design space. | `docs/history.md` | +| [nostr-commerce-skill](https://github.com/welliv/nostr-commerce-skill) | Informational / agent-friendly reference | Shows scenario-oriented commerce modeling useful for docs and agent workflows. | `docs/architecture.md`, `examples/README.md`, `AGENTS.md` | +| [Colabonate NIP-115 draft](https://github.com/Colabonate/nips/blob/colabonate-freedom-protocol/115.md) | Experimental proposal | Active checkout, escrow, and dispute design work. | `proposals/escrow.md` | +| [nostr-protocol/nips PR 2323](https://github.com/nostr-protocol/nips/pull/2323) | Active RFC context | Discussion context for on-graph checkout, escrow, and disputes. | `proposals/escrow.md` | +| [Pontmore PIP-00 agent definition](https://github.com/pontmore/protocol/blob/main/PIP-00-agent-definition.md) | Experimental / informational | Agent definition work that may inform future agent discovery or service coordination. | `proposals/escrow.md`, future proposals | +| [Switchboard escrow architecture](https://github.com/samuelralak/switchboard/blob/master/docs/escrow-architecture.md) | Implementation / informational | Escrow architecture reference for future integration notes. | `proposals/escrow.md` | + +The repo should acknowledge contributors including Gamma Markets, NIP-15 authors, Shopstr, Plebeian, Conduit, Colabonate, Switchboard, and related Nostr commerce builders without presenting this refactor as replacing their work. + +## 3. Proposed Information Architecture + +Use a small file-based structure: + +```text +/ + README.md + SPEC.md + AGENTS.md + docs/ + refactor-plan.md + history.md + compatibility.md + terminology.md + architecture.md + pillars/ + items.md + orders.md + payments.md + delivery.md + lanes/ + ecommerce.md + examples/ + README.md + proposals/ + escrow.md +``` + +Purpose: + +- `README.md`: map, compatibility promise, status legend, and exact external links. +- `SPEC.md`: byte-identical current spec snapshot. +- `AGENTS.md`: contributor and agent guardrails. +- `docs/`: explanatory, historical, compatibility, and planning docs. +- `pillars/`: broad homes for current material and future extensions. +- `lanes/`: market-specific lanes, with e-commerce as the first fully expressed lane. +- `examples/`: future runnable or copyable examples without changing the spec. +- `proposals/`: experimental references and proposal workspaces. + +## 4. Migration / Transposition Strategy + +Every moved/copied section must preserve meaning. Current text can be copied unchanged into split views while `SPEC.md` preserves the original contiguous document. + +| Current section | Proposed location | Strategy | +| --- | --- | --- | +| `Protocol Requirements` | `lanes/ecommerce.md` | Copy unchanged. | +| `Core Protocol Components` | `docs/architecture.md` | Copy unchanged and add non-normative pillar navigation. | +| `Merchant Preferences` | `pillars/payments.md` and `docs/architecture.md` | Copy unchanged. | +| `Product Listing` | `pillars/items.md` | Copy unchanged. | +| `Product Collection` | `pillars/items.md` | Copy unchanged. | +| `Drafts` | `pillars/items.md` | Copy unchanged. | +| `Shipping Option` | `pillars/delivery.md` | Copy unchanged. | +| `Order Communication Flow and Payment Processing` intro | `pillars/orders.md` | Copy unchanged for context. | +| `Order Creation` | `pillars/orders.md` | Copy unchanged. | +| `Payment Request` | `pillars/payments.md` | Copy unchanged. | +| `Order Status Updates` | `pillars/orders.md` | Copy unchanged. | +| `Shipping Updates` | `pillars/delivery.md` | Copy unchanged. | +| `General Communication` | `pillars/orders.md` | Copy unchanged. | +| `Payment Receipt` | `pillars/payments.md` | Copy unchanged. | +| `Product Reviews` | `pillars/items.md` | Copy unchanged. | +| `Implementation Guidelines` payment material | `pillars/payments.md` | Copy unchanged. | + +Safe now: + +- Move/copy text unchanged. +- Add navigation and cross-links. +- Add source links, compatibility notes, history, and proposal workspaces. +- Label sections as normative, explanatory, historical, or experimental. + +Defer: + +- New event kinds. +- Escrow semantics. +- Payment tag redesign. +- Order receipt redesign. +- NIP-99 recomposition. +- Generic market abstractions that change current e-commerce behavior. +- Any wording change that alters MUST, SHOULD, or MAY meaning. + +## 5. Backward Compatibility Strategy + +The PR should preserve: + +- event kind numbers +- tag names +- tag ordering in examples +- field names +- JSON shapes +- required and optional semantics +- payment preference values +- order `type` values +- order and shipping `status` values +- payment proof shapes +- current examples +- upstream links +- NIP-99 expectations +- current e-commerce flow wording + +Validation checks: + +- `SPEC.md` must match the pre-refactor `README.md`. +- Inventory kind numbers before and after. +- Inventory tag names before and after. +- Inventory normative keywords before and after. +- Review all copied code fences against `SPEC.md`. +- Confirm escrow remains proposal-only. + +## 6. Normative vs Non-Normative Strategy + +Normative: + +- `SPEC.md` +- copied current spec sections in `pillars/` and `lanes/` + +Explanatory: + +- `docs/architecture.md` navigation text +- `docs/terminology.md` +- `examples/README.md` + +Historical: + +- `docs/history.md` + +Experimental: + +- `proposals/escrow.md` +- future proposal documents + +Future proposals may become normative only through explicit PRs that identify compatibility impact and migration requirements. + +## 7. Specific PR Implementation Plan + +Commit 1: repo map and agent guidance. + +- Add `docs/refactor-plan.md`. +- Add `AGENTS.md`. +- Compatibility note: planning and guardrails only. + +Commit 2: compatibility snapshot. + +- Add `SPEC.md` as a byte-identical copy of the current `README.md`. +- Compatibility note: current spec remains available in one file. + +Commit 3: history and compatibility docs. + +- Add `docs/history.md`, `docs/compatibility.md`, `docs/terminology.md`, and `docs/architecture.md`. +- Compatibility note: explanatory only. + +Commit 4: pillar and lane transposition. + +- Add `pillars/items.md`, `pillars/orders.md`, `pillars/payments.md`, `pillars/delivery.md`, and `lanes/ecommerce.md`. +- Compatibility note: copied current spec text, no semantic changes. + +Commit 5: examples and proposal workspace. + +- Add `examples/README.md` and `proposals/escrow.md`. +- Compatibility note: examples are future workspace; escrow remains optional and experimental. + +Commit 6: root README cleanup. + +- Replace root README with navigation, compatibility, status legend, and exact references. +- Compatibility note: root README points to `SPEC.md` instead of redefining protocol. + +## 8. Open Questions + +These are explicitly out of scope for the structural refactor: + +- Whether new kinds are needed for checkout, payment status, escrow, disputes, or delivery milestones. +- Whether current NIP-99 structures are sufficient for non-e-commerce lanes. +- Whether order receipt shape should remain private, public, hybrid, or revealable only during disputes. +- How payment status events should be represented, if at all. +- How escrow/arbitration services should be discovered. +- How privacy-preserving dispute disclosure should work. +- How fiat and external payments should be referenced. +- How much lane-specific material belongs in the base spec. +- How outside contributors should upstream their proposals. + +## 9. Risks + +- Accidentally changing spec meaning during reorganization. +- Breaking apps that already implement the current spec. +- Overcomplicating the repo. +- Prematurely standardizing escrow. +- Alienating prior contributors. +- Making e-commerce harder to implement while trying to generalize. +- Inventing new events unnecessarily. +- Creating too many folders. +- Making the spec hostile to implementers or agents. +- Misrepresenting external specs through paraphrase. + +## 10. Acceptance Criteria + +The refactor is successful when: + +- Existing apps remain compatible. +- Current implementation-sensitive details are preserved. +- NIP-99 remains the base listing primitive. +- Current NIP-99 standards are referenced exactly. +- E-commerce still works clearly. +- Non-e-commerce market flows have obvious future homes. +- Payments are organized in a payment-agnostic way without changing current payment behavior. +- Escrow has a place without being prematurely finalized. +- Delivery is broad enough for physical goods, digital goods, services, rides, lodging, and fulfillment. +- History is acknowledged respectfully. +- External proposals are linked exactly and given room to develop. +- The repo is easier for humans and agents to navigate. +- Implementers can tell which parts are normative, explanatory, historical, and experimental. +- The PR is a transposition, not a recomposition. diff --git a/docs/terminology.md b/docs/terminology.md new file mode 100644 index 0000000..0a25c8d --- /dev/null +++ b/docs/terminology.md @@ -0,0 +1,29 @@ +# Terminology + +Status: explanatory reader aid. + +This page helps readers navigate the repository. It does not redefine protocol behavior. If a definition here conflicts with [../SPEC.md](../SPEC.md), [../SPEC.md](../SPEC.md) controls. + +## Pillars + +- Items: what is being offered, listed, updated, discovered, categorized, priced, reviewed, or collected. +- Orders: buyer/seller intent and communication around order creation, status, cancellation, and order-linked messages. +- Payments: payment preferences, payment requests, invoices, proofs, receipts, payment services, and future payment rails. +- Delivery: shipping, pickup, physical delivery, digital delivery, ride or service fulfillment, lodging fulfillment, milestones, and completion signals. + +## Lanes + +A lane is a market-specific flow that uses the shared pillars. + +The current fully expressed lane is e-commerce. Future lanes might include ride-sharing, room-sharing, restaurant delivery, real estate listings, job postings, service marketplaces, digital goods, and other open-market flows. Those future lanes are not normative until explicitly specified. + +## Status Labels + +- Normative: current protocol requirements and future accepted requirements. +- Explanatory: guidance for readers and implementers that does not change requirements. +- Historical: prior work, acknowledgments, and source lineage. +- Experimental: proposals, design space, and integration notes. + +## Current Coordination Point + +[NIP-99](https://github.com/nostr-protocol/nips/blob/master/99.md) is the current coordination point for listing primitives in the Open Markets design space. Open Markets organizes interoperable flows above that base primitive while preserving current e-commerce compatibility. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..a650a4c --- /dev/null +++ b/examples/README.md @@ -0,0 +1,14 @@ +# Examples + +Status: explanatory workspace. + +This directory is reserved for examples that help implementers and agents understand current Open Markets flows. + +Examples added here should: + +- preserve existing event kinds, tag names, tag shapes, and payload structures +- link back to the normative section they illustrate +- avoid introducing new requirements +- state whether they are copied from [../SPEC.md](../SPEC.md), derived from current spec text, or experimental + +Do not use examples to introduce new semantics. New protocol behavior belongs in a proposal first. diff --git a/lanes/ecommerce.md b/lanes/ecommerce.md new file mode 100644 index 0000000..b30d85b --- /dev/null +++ b/lanes/ecommerce.md @@ -0,0 +1,39 @@ +# E-commerce Lane + +Status: normative transposition of current e-commerce requirements. + +This lane preserves the current Open Markets e-commerce flow as the first fully expressed market lane. The canonical contiguous compatibility snapshot remains [../SPEC.md](../SPEC.md). The copied section below is unchanged from the pre-refactor specification. + +## 1. Protocol Requirements + +The protocol defines both required core components and optional features to support diverse marketplace needs. + +### Required Components +Implementations MUST support the following core features: + +- Product listing events (Kind: 30402) +- Product collection events (Kind: 30405) for product-to-collection references +- Merchant's preferences +- Order communication and processing via [NIP-17](17.md) encrypted messages + +### Optional Components +These features MAY be implemented based on specific marketplace needs: + +- Extended product metadata +- Shipping options (Kind: 30406) +- Product collections (Kind: 30405) +- Drafts following [NIP-37](37.md) +- Product reviews (Kind: 31555) +- Service assisted order and payment processing + +#### Watch-only clients +Watch-only clients are applications that allow users to display products without implementing full e-commerce capabilities. These clients don't need to support all required components - product rendering alone can be sufficient. However, ideally, they should also handle logic for looking up collections, reviews, and shipping options. Support for order communication using [NIP-17](17.md) is optional. + +## Related Pillars + +- Items: [../pillars/items.md](../pillars/items.md) +- Orders: [../pillars/orders.md](../pillars/orders.md) +- Payments: [../pillars/payments.md](../pillars/payments.md) +- Delivery: [../pillars/delivery.md](../pillars/delivery.md) + +The existing standard e-commerce flow remains in [../docs/architecture.md](../docs/architecture.md). Future lanes can be added without changing this lane's current requirements. diff --git a/pillars/delivery.md b/pillars/delivery.md new file mode 100644 index 0000000..2d9dc3c --- /dev/null +++ b/pillars/delivery.md @@ -0,0 +1,174 @@ +# Delivery Pillar + +Status: normative transposition of current shipping option and shipping update material. + +This file copies the implementation-sensitive delivery sections from [../SPEC.md](../SPEC.md). The delivery pillar is broad enough to hold future physical, digital, service, ride, lodging, pickup, and milestone fulfillment work, but this PR does not add new delivery semantics. + +### Shipping Option (Kind: 30406) +A specialized event type for defining shipping methods, costs, and constraints. Shipping options can be published by merchants or third-party providers (delivery companies, DVMs, etc.) and referenced by product listings or collections. + +**Content**: Optional human-friendly shipping description + +**Required tags**: +- `d`: Unique shipping option identifier +- `title`: Display title for the shipping method +- `price`: Base cost array `[, ]` +- `country`: Array of ISO 3166-1 alpha-2 country codes `[, , ...]` +- `service`: Service type ("standard", "express", "overnight", "pickup") + +**Optional tags**: +- Extra details: + - `carrier`: The name of the carrier that will be used for the delivery +- Time and Location: + - `region`: Array of ISO 3166-2 region codes for which shipping method is available `[, , ...]` + - `duration`: Delivery window `[, , ]` using ISO 8601 duration units + - min: Minimum delivery time + - max: Maximum delivery time + - unit: "H" (hours), "D" (days), "W" (weeks) + - `location`: Physical address for pickup + - `g`: Geohash for precise location + +- Constraints: + - `weight-min`: Minimum weight `[, ]` (ISO 80000-1) + - `weight-max`: Maximum weight `[, ]` + - `dim-min`: Minimum dimensions `[xx, ]` + - `dim-max`: Maximum dimensions `[xx, ]` + +- Price Calculations: + - `price-weight`: Per weight pricing `[, ]` + - `price-volume`: Per volume pricing `[, ]` + - `price-distance`: Per distance pricing `[, ]` + +```jsonc +{ + "kind": 30406, + "created_at": , + "content": "", + "tags": [ + // Required tags + ["d", ""], + ["title", ""], + ["price", "", ""], + ["country", "", "...", "..."], // Array of country codes + ["service", ""], + + // Extra details + ["carrier",""] + + // Time and Location + ["region", "", "...", "..."], // Array of region codes + ["duration", "", "", ""], // ISO 8601 duration units (H/D/W) + ["location", "
"], + ["g", ""], + + // Constraints + ["weight-min", "", ""], + ["weight-max", "", ""], + ["dim-min", "xx", ""], + ["dim-max", "xx", ""], + + // Price Calculations + ["price-weight", "", ""], + ["price-volume", "", ""], + ["price-distance", "", ""] + ] +} +``` + +#### Implementation Examples + +Local Pickup: +```jsonc +{ + "kind": 30406, + "created_at": 1703187600, + "content": "Downtown Store Pickup", + "tags": [ + ["d", "downtown-pickup"], + ["title", "Downtown Store Pickup"], + ["price", "0", "USD"], + ["country", "US"], + ["region", "US-FL"], + ["service", "pickup"], + ["location", "123 Main St, Downtown, FL"], + ["g", "dhwm9c4ws"] + ] +} +``` + +Standard Shipping: +```jsonc +{ + "kind": 30406, + "created_at": 1703187600, + "content": "Standard Regional Shipping", + "tags": [ + ["d", "standard-regional"], + ["title", "Standard Shipping"], + ["price", "5.99", "USD"], + ["country", "US"], + ["region", "US-FL"], + ["service", "standard"], + ["duration", "24", "72", "H"], // 24-72 hours delivery window + ["weight-max", "30", "kg"], + ["dim-max", "120x60x60", "cm"], + ["price-weight", "0.75", "USD", "kg"] + ] +} +``` + +#### Notes +1. Event Management: + - Create separate events for each distinct shipping option + - Each option needs a unique `d` tag identifier + - Merchants can reference third-party shipping options + +2. Shipping Rules: + - Physical pickup requires location and/or geohash + - Weight/dimension constraints use ISO 80000-1 units + +3. Client Behavior: + - Group options by service type and location + - Use geohash for distance-based sorting + - Validate package constraints before offering options + +#### 4. Shipping Updates +Sent by merchant to provide delivery tracking and status information. + +**Content:** (Optional) Human readable shipping status and tracking information + +**Required tags:** +- `p`: Buyer's public key +- `subject`: Human-friendly subject line for shipping updates +- `type`: Must be "4" to indicate shipping update +- `order`: The original order identifier +- `status`: Current shipping status: + - `processing`: Order is being prepared for shipping + - `shipped`: Package has been handed to carrier + - `delivered`: Successfully delivered to destination + - `exception`: Delivery issue or delay encountered + +**Optional tags:** +- `tracking`: Carrier's tracking number +- `carrier`: Name of shipping carrier +- `eta`: Expected delivery time as unix timestamp + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "shipping-info"], + ["type", "4"], // Shipping update + ["order", ""], + + // Shipping details + ["status", ""], // processing|shipped|delivered|exception + ["tracking", ""], + ["carrier", ""], + ["eta", ""], + ], + "content": "Shipping status and tracking information" +} +``` diff --git a/pillars/items.md b/pillars/items.md new file mode 100644 index 0000000..5c232cf --- /dev/null +++ b/pillars/items.md @@ -0,0 +1,235 @@ +# Items Pillar + +Status: normative transposition of current listing, collection, draft, and review material. + +This file copies the implementation-sensitive item sections from [../SPEC.md](../SPEC.md). Do not change kind numbers, tag names, tag shapes, required/optional semantics, examples, or normative keywords in this transposition. + +### Product Listing (Kind: 30402) + +Products are the core element in a marketplace. Each product listing MUST contain basic metadata and MAY contain additional details. Their configuration is the source of truth, overriding other possible configurations of other market elements such as collections, no configuration is cascaded to products, they MUST explicitly reference an attribute to inherit it. + +**Content**: Product description, markdown is allowed +**Required tags**: +- `d`: Unique product identifier for referencing the listing +- `title`: Product name/title for display +- `price`: Price information array `[, , ]` + - amount: Decimal number (e.g., "10.99") + - currency: ISO 4217 code (e.g., "USD", "EUR") + - frequency: Optional subscription interval using ISO 8601 duration units (e.g. 'D' for daily, 'W' for weekly, 'Y' for yearly). + +**Optional tags**: +- Product Details: + - `type`: Product classification `[, ]` + - type: "simple", "variable", or "variation" + - format: "digital" or "physical" + - Default/if not present: type: "simple", format: "digital" + - `visibility`: Display status ("hidden", "on-sale", "pre-order"). Default/if not present: "on-sale" + - `stock`: Available quantity as integer + - `summary`: Short product description + - `spec`: Product specifications `[, ]`, can appear multiple times + +- Media: + - `image`: Product images `[, , ]`, MAY appear multiple times + - url: Direct image URL + - dimensions: Optional, in pixels, "x" format, if not present the place in the array should be respected by using an empty string `""` + - sorting order: Optional integer for order sorting. Values are sorted from lowest to highest, independent of starting value (not restricted to start with 0 or 1) + +- Physical Properties: + - `weight`: Product weight `[, ]` using ISO 80000-1 + - `dim`: Dimensions `[xx, ]` using ISO 80000-1 + +- Location: + - `location`: Human-readable location string or collection coordinates + - `g`: Geohash for precise location lookup or collection coordinates + +- Organization: + - `t`: Product categories/tags, MAY appear multiple times + - `a`: Product reference "30402::", MUST appear only once to reference parent products in a variable/variation configuration + - `a`: Collection reference "30405::", MAY appear multiple times + - `shipping_option`: Shipping options, MAY appear multiple times + - Format: "30406::" for direct options + - Format: "30405::" for collection shipping + - `extra-cost`: Optional third element in the array, to add extra cost (in the product's currency) for the shipping method. In case of reference a collection the extra cost should be applied to all shipping options from the collection. + +```jsonc +{ + "kind": 30402, + "created_at": , + "content": "", + "tags": [ + // Required tags + ["d", ""], + ["title", ""], + ["price", "", "", ""], + + // Product details + ["type", "", ""], // Defaults: simple, digital + ["visibility", ""], // Default: on-sale + ["stock", ""], // Available quantity + ["summary", ""], + + // Media and specs + ["image", "", "", ""], + ["spec", "", ""], // Product specifications (e.g., "screen-size", "21 inch"). MAY appear multiple times + + // Physical properties (for shipping) + ["weight", "", ""], // ISO 80000-1 units (g, kg, etc) + ["dim", "xx", ""], // ISO 80000-1 units (mm, cm, m) + + // Location + ["location", "
"], + ["g", ""], + + // Classifications + ["t", ""], + + // References + ["shipping_option", "<30406|30405>::", ""], // Shipping options or collection, MAY appear multiple times + ["a", "30405::"] // Product collection + ] +} +``` + +#### Notes +1. Product Configuration: + - Products can be simple, variable (with options), or variations of variable products + - Digital products skip shipping requirements + - Visibility controls product display status + +2. Variable products: + - The parent or "root" product should use `variable` as value for `type` + - The variations of the parent product should use `variation` as value for `type`. + - Variations MUST include an `a` tag pointing to the `variable` parent product. + +2. Shipping Rules: + - Shipping options can be defined directly by pointing to a shipping event, or inherited from collections + - If the product specifies product-specific shipping, and also from a collection, shipping options MUST be merged. + +3. Collections and Categories: + - Products can refer to one o multiple collections using `a` tags, whether or not they are part of it, for discoverability purposes. + - Categories ("t" tags) aid in discovery and organization + +4. Location Support: + - Optional location data aids in local marketplace features, they can point to a collection event to inherit it's value + - Geohash enables precise location-based searches, they can point to a collection event to inherit it's value + +### Product Collection (Kind: 30405) +A specialized event type using [NIP-51](51.md) like list format to organize related products into groups. Collections allow merchants or any user to create meaningful product groupings and share common attributes that products can also reference, establishing one-to-many relationships. + +**Content**: Optional collection description + +**Required tags**: +- `d`: Unique collection identifier +- `title`: Collection display name/title +- `a`: Product references `["a", "30402::"]` + - Multiple product references allowed + - References must point to valid product listings + +**Optional tags**: +- Display: + - `image`: Collection banner/thumbnail URL + - `summary`: Brief collection description + +- Location: + - `location`: Human-readable location string + - `g`: Geohash for precise location lookup + +- Reference Options: + - `shipping_option`: Available shipping options `["shipping_option", "30406::"]`, MAY appear multiple times + +```jsonc +{ + "kind": 30405, + "created_at": , + "content": "", + "tags": [ + // Required tags + ["d", ""], + ["title", ""], + ["a", "30402::"], // Product reference + + // Optional tags + ["image", ""], + ["summary", ""], + + // Location + ["location", ""], + ["g", ""], + + // Reference Options + ["shipping_option", "30406::"], // Available shipping options, MAY appear multiple times + ] +} +``` + +#### Notes +1. Collection Management: + - Collections can contain any number of products + - Products can belong to multiple collections + +2. Reference Model: + - Collection settings (shipping, location, geohash) serve as references only + - Products MUST explicitly reference collection resources to inherit collection attributes (e.g. shipping, location, geohash). + - No automatic cascading of settings to products + +3. Location Support: + - Optional location data helps with marketplace organization + - Enables geographic grouping of related products + +### Drafts +Products and collections can be saved as private drafts while being prepared for publication. This allows merchants to work on listings before making them publicly visible. Implementation MUST follow [NIP-37](https://github.com/nostr-protocol/nips/blob/master/37.md) for draft management. + +## 5. Product Reviews (Kind: 31555) + +Product reviews follow [NIP-85](https://github.com/nostr-protocol/nips/blob/b1432b705f553bde6c4eb5fcfde8525d2913b477/85.md) and [QTS](https://habla.news/u/arkinox@arkinox.tech/DLAfzJJpQDS4vj3wSleum) guidelines with additional marketplace-specific rating criteria. Reviews provide structured feedback about products, merchants, and the overall purchase experience. + +**Content:** Detailed review text + +**Required tags:** +- `d`: Reference to product `["d", "a:30402::"]` +- `rating`: Primary rating `["rating", "", "thumb"]` + - score: 0 (negative) to 1 (positive) + - "thumb" label MUST be present as primary rating + +**Optional tags:** +- Additional Ratings: + - `rating`: Category scores `["rating", "", ""]` + - score: 0 to 1 (supports fractional values) + - category: These are optional, some standard categories may include: + - "value": Price vs quality + - "quality": Product quality + - "delivery": Shipping experience + - "communication": Merchant responsiveness + +```jsonc +{ + "kind": 31555, + "created_at": , + "tags": [ + // Required tags + ["d", "a:30402::"], + ["rating", "1", "thumb"], // Primary rating + + // Optional rating categories + ["rating", "0.8", "value"], + ["rating", "1.0", "quality"], + ["rating", "0.6", "delivery"], + ["rating", "0.9", "communication"] + ], + "content": "Detailed review text" +} +``` + +#### Rating Calculation +The final score combines the primary "thumb" rating (50% weight) with additional category ratings (50% combined weight): + +``` +Total Score = (Thumb × 0.5) + (0.5 × (∑(Category Ratings) ÷ Number of Categories)) +``` + +#### Notes +1. Rating System: + - Primary thumb rating is required, it determines the overall an overall rating. + - Additional categories are optional + - Scores support fractional values between 0-1 + - Custom categories can be added diff --git a/pillars/orders.md b/pillars/orders.md new file mode 100644 index 0000000..160b8f6 --- /dev/null +++ b/pillars/orders.md @@ -0,0 +1,145 @@ +# Orders Pillar + +Status: normative transposition of current order communication material. + +This file copies the implementation-sensitive order sections from [../SPEC.md](../SPEC.md). Payment request, payment receipt, and shipping update details are also represented in the payment and delivery pillars for navigation, but the canonical contiguous context remains [../SPEC.md](../SPEC.md). + +## 4. Order Communication Flow and Payment Processing + +Order processing and status updates use [NIP-17](17.md) encrypted direct messages, with three event kinds serving different purposes: + +- Kind `14`: Regular communication between parties + - General inquiries and responses + - Order clarifications + - Subject can be order ID or empty + +- Kind `16`: Order processing and status. These messages include a `type` field that indicates the specific kind of message + - Order creation and details. `type`: 1 + - Payment requests. `type`: 2 + - Status updates. `type`: 3 + - Shipping information. `type`: 4 + +- Kind `17`: Payment receipts and verification + +Message direction is determined by the author, and `p` tag: +- Buyer → Merchant: event author is the buyer, `p` tag contains merchant's pubkey +- Merchant → Buyer: event author is the merchant, `p` tag contains buyer's pubkey + +The payment request flow can operate in two modes: +1. Direct: Merchant processes requests manually. Payment request is initiated by the merchant +2. Service-assisted: Merchant's payment service handles requests. Payment request is initiated by the buyer + +### Message Types +#### 1. Order Creation +Sent by buyer to initiate order process. + +**Content:** (Optional) Human readable order notes or special requests + +**Required tags:** +- `p`: Merchant's public key +- `subject`: Human-friendly subject line for order information +- `type`: Must be "1" to indicate order creation +- `order`: Unique identifier for the order +- `amount`: Total order amount in satoshis +- `item`: Product reference in format "30402::" with quantity. MAY appear multiple times + +**Optional tags:** +- `shipping`: Reference to shipping option "30406::" +- `address`: Shipping address details +- `email`: Customer email for contact +- `phone`: Customer phone number for contact +- Other optional tags can be added with more details from the customer + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", ""], + ["type", "1"], // Order creation + ["order", ""], // Unique order identifier + ["amount", ""], + + // Order items (can repeat) + ["item", "30402::", ""], + + // Shipping details + ["shipping", "30406::"], + ["address", ""], + + // Customer contact + ["email", ""], // Optional + ["phone", ""], // Optional + ], + "content": "Order notes or special requests" +} +``` + +#### 3. Order Status Updates +Once the merchant receives payment, they MUST update the status to "confirmed". Status updates can be sent as soon as a new order is acknowledged, initially setting the status to "pending". The "pending" status is optional and can be skipped, starting directly with "confirmed" once payment is received. + +**Content:** (Optional) Human readable status update + +**Required tags:** +- `p`: Buyer's public key +- `subject`: Human-friendly subject line for status updates +- `type`: Must be "3" to indicate status update +- `order`: The original order identifier +- `status`: Current order status: + - `pending`: Order received but awaiting payment + - `confirmed`: Payment received and verified + - `processing`: Order is being prepared + - `completed`: Order fulfilled + - `cancelled`: Order cancelled by either party + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-info"], + ["type", "3"], // Status update + ["order", ""], + + // Status information + ["status", ""], // pending|confirmed|processing|completed|cancelled + ], + "content": "Human readable status update" +} +``` + +Buyers may also send a status update to cancel an order, ideally before the status has been set to "confirmed": + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-info"], + ["type", "3"], // Status update + ["order", ""], + + // Status information + ["status", ""], // cancelled + ], + "content": "Human readable status update" +} +``` + +#### 5. General Communication +Used for any order-related messages (Kind 14) + +```jsonc +{ + "kind": 14, + "tags": [ + // Required tags + ["p", ""], + ["subject", ""], // Optional, can be empty + ], + "content": "General communication message" +} +``` diff --git a/pillars/payments.md b/pillars/payments.md new file mode 100644 index 0000000..bdbf1d7 --- /dev/null +++ b/pillars/payments.md @@ -0,0 +1,223 @@ +# Payments Pillar + +Status: normative transposition of current merchant preference, payment request, and payment receipt material. + +This file copies the implementation-sensitive payment sections from [../SPEC.md](../SPEC.md). Do not change payment preference values, payment tag shapes, amount semantics, receipt examples, or NIP references in this transposition. + +### Merchant Preferences +Merchants MAY specify preferences for how they want users to interact with them, including which applications to use and payment methods to accept. These preferences ensure a consistent experience and streamline operations. Merchants indicate their preferences through two mechanisms: + +1. Application Preferences ([NIP-89](89.md)): +- The recommended application MUST publish a kind `31990` event +- The merchant MUST publish a kind `31989` event recommending that application + +2. Payment Preferences: +- Set via `payment_preference` tag in the merchant's kind `0` event +- Valid values: `manual | ecash | lud16` +- Defaults to `manual` if not specified + +Applications implementing this NIP MUST handle preferences as follows: + +1. When `payment_preference` is `manual`: +- If merchant recommends an app: MUST direct users to that app +- If no app recommendation: Use traditional interactive flow (buyer places order and waits for merchant's payment request) + +2. When `payment_preference` is `ecash` or `lud16`: +- If merchant recommends an app: SHOULD direct users there first, but they MAY also offer to continue if compatible with the payment preference +- If no recommendations: Use specified payment method directly + +3. When no preferences are set: +- Use traditional interactive flow + - Buyer sends order + - Wait for merchant's payment request + +Buyers can verify merchant preferences by: +- Checking kind `31990` events for recommended applications +- Checking kind `0` events for payment preferences + +This verification helps buyers follow merchant-approved paths and avoid potential scams or poor experiences. + +#### 2. Payment Request +There are two variants depending on payment processing mode: manual or automatic processing. After the buyer pays the payment request, they MUST send a payment receipt to the merchant using a kind:`17` dm. + +##### Manual Processing (merchant → buyer) + +In this mode, the merchant manually initiates the payment by sending a payment request to the buyer. This requires either: +- The merchant being online to process requests, or +- Having an automated system for processing payment requests, which can be run by the merchant or a service they rely on according to merchant preferences. + +Important considerations: +- Merchant shouldn't have a recommended application in their merchant's preferences +- Final price may differ from the order creation time +- Merchants decide whether to honor original prices +- Buyers can cancel orders if they don't agree with price changes + +**Content:** (Optional) Human readable payment instructions and notes + +**Required tags:** +- `p`: Buyer's public key +- `subject`: Human-friendly subject line for order payment requests +- `type`: Must be "2" to indicate payment request +- `order`: The unique order identifier from the original order +- `amount`: Total payment amount in satoshis + +**Optional tags:** +- `payment`: Payment method details, can appear multiple times for different options: + - Lightning format: `["payment", "lightning", ""]` + - Bitcoin format: `["payment", "bitcoin", ""]` + - eCash format: `["payment", "ecash", ""]` +- `expiration`: Include if the payment format has a defined expiration time + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-payment"], + ["type", "2"], // Payment request + ["order", ""], + ["amount", ""], + + // Payment options (can include multiple) + ["payment", "lightning", ""], + ["payment", "bitcoin", ""], + ["payment", "ecash", ""], + ["expiration", ""], + ], + "content": "Payment instructions and notes" +} +``` + +##### Automatic Processing (buyer → merchant) +In this mode, the merchant MUST set valid payment options in their kind:`0` event (such as `cashu` or `lud16`). The key difference is that the buyer initiates the payment request using information provided by the merchant. For merchants using `manual` payment preference, they SHOULD use [NIP-89](89.md) to specify their preferred payment processing service, which can then automatically handle payment requests on their behalf, as described in the merchant preferences section above. + +```jsonc +{ + "kind": 16, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-payment"], + ["type", "2"], // Payment request + ["order", ""], + ["amount", ""], + + // Payment details from service + ["payment", "lightning", ""], + ["payment", "bitcoin", ""], + ["payment", "ecash", ""], + ], + "content": "Service-generated payment details" +} +``` + +#### 6. Payment Receipt +Sent by buyer to confirm payment completion. The receipt can include proof of payment from any payment system, including traditional fiat gateways. + +**Content:** (Optional) Human readable payment confirmation details + +**Required tags:** +- `p`: Merchant's public key +- `subject`: Human-friendly subject line for order receipt +- `order`: The original order identifier +- `payment`: Payment proof details (at least one required): + - Generic format: `["payment", "", "", ""]` + - Common examples: + - Lightning: `["payment", "lightning", "", ""]` + - Bitcoin: `["payment", "bitcoin", "
", ""]` + - eCash: `["payment", "ecash", "", ""]` + - Fiat: `["payment", "fiat", "", ""]` +- `amount`: Payment amount + +```jsonc +{ + "kind": 17, + "tags": [ + // Required tags + ["p", ""], + ["subject", "order-receipt"], + ["order", ""], + + // Payment proof (one required) + ["payment", "", "", ""], + ["payment", "lightning", "", ""], + ["payment", "bitcoin", "
", ""], + ["payment", "ecash", "", ""], + ["payment", "fiat", "", ""], + + // Metadata + ["amount", ""] + ], + "content": "Payment confirmation details" +} +``` + +#### Notes +1. Message Flow: + - Receipts should include verifiable proofs + +2. Payment Processing: + - Manual mode provides more flexibility + - Automatic mode enables faster processing and convenience + - Multiple payment options can be offered + +3. Status Tracking: + - Use consistent status codes + - Include timestamps for all updates + - Provide clear user messages + +## 6. Implementation Guidelines + +### Payment Flow Details + +#### Payment Preferences +Merchants can specify their payment preferences in their kind:`0` event using the `payment_preference` tag: +``` +["payment_preference", ""] +``` + +If not present, it defaults to `manual`. The preferences are processed in this order of complexity: +1. Manual (default): Merchant provides payment requests directly +2. eCash: Ideally the merchant has a kind `10019` event to know what mint they prefer. + - If the `10019` event is not present, payment can be made by sending the token embedded directly in the order receipt message from a previously set mint (whether default or user selected); otherwise, the merchant's preferred mint SHOULD be used. +3. Lightning: Requires `lud16` or related lightning fields in kind `0` + +#### Payment Processing Scenarios + +1. **Manual Processing** + - Merchant initiates payment request + - Used when no application is recommended or automatic preferences are set + - Merchant must manually send payment requests + - Buyer waits for merchant's payment instructions + - Merchants can have their own service that listens for new orders and then sends the payment request + +2. **Automatic Processing** + - Buyer initiates payment request + - Requires a valid `payment_preference` in merchant's kind `0` + - Service-Based Processing processing if `payment_preference` is `manual` and the merchant have a recommended application + - Supports automatic payments via: + - eCash tokens (locked to merchant's pubkey) + - Lightning (using merchant's `lud16` address) + +3. **Service-Based Processing** + - Merchant MUST set `payment_preference` to `manual` + - Merchant SHOULD have a [NIP-89](89.md) kind `31989` event recommending their preferred service + - Buyers can immediately request payment using the service + - Service handles payment details and completion monitoring + +For all scenarios: +- Buyer MUST send payment receipt after completion +- Message direction is determined by `p` tag +- Merchant's [NIP-89](89.md) application preferences SHOULD be respected + +### Marketplace Application Role +Marketplace applications can optionally facilitate the order processing and payment request by: + +1. Generating payment requests based on merchant preferences when buyers initiate orders +2. Verifying payments and generating receipts automatically by prompting the buyer to sign the event +3. Helping merchants managing inventory and order status updates +4. Coordinating shipping information +5. Price calculations + +This provides a smoother user experience while maintaining the ability for direct merchant-buyer communication as a fallback mechanism. diff --git a/proposals/escrow.md b/proposals/escrow.md new file mode 100644 index 0000000..5d968a7 --- /dev/null +++ b/proposals/escrow.md @@ -0,0 +1,50 @@ +# Escrow, Arbitration, and Agent Proposals + +Status: experimental reference workspace. + +This page creates room for checkout, escrow, arbitration, dispute, and agent-related work without making any design canonical in the current Open Markets specification. + +## Current Status + +Escrow is not mandatory in the current Open Markets spec. + +This repository does not currently decide: + +- whether escrow should be merchant-run, third-party, federated, ecash-based, Lightning-based, on-chain, fiat-based, or hybrid +- whether escrow state should be public, private, encrypted, revealable, or projected from private receipts +- whether a marketplace should ever be a custodian of funds +- which arbiter discovery mechanism is preferred +- which payment proof tag shape should be canonical for escrow +- whether checkout state should extend current `kind:16` messages or use new public events + +## Exact References + +- [Colabonate NIP-115 draft](https://github.com/Colabonate/nips/blob/colabonate-freedom-protocol/115.md) +- [nostr-protocol/nips PR 2323](https://github.com/nostr-protocol/nips/pull/2323) +- [Pontmore PIP-00 agent definition](https://github.com/pontmore/protocol/blob/main/PIP-00-agent-definition.md) +- [Switchboard escrow architecture](https://github.com/samuelralak/switchboard/blob/master/docs/escrow-architecture.md) + +## Open Design Direction + +A possible future architecture may explore: + +1. Merchant runs marketplace-standard escrow mint, register, or software. +2. Buyer receives a signed order receipt locally. +3. Merchant receives order details. +4. Marketplace may receive only a minimal hash, commitment, or verification ping. +5. If there is no dispute, marketplace never learns full transaction details. +6. If a dispute arises, either party reveals the receipt packet and supporting evidence to the marketplace or arbiter. + +This is context only. It is not a current normative requirement. + +## Contribution Guidance + +Future escrow or arbitration proposals should: + +- reference existing work exactly +- state whether they are compatible with current encrypted order messages +- state whether they require new event kinds +- state whether they require public checkout state +- state what information is revealed to marketplaces, arbiters, relays, and counterparties +- state how existing e-commerce implementations remain compatible +- avoid making escrow mandatory unless a future accepted spec explicitly does so