Originally posted by DIYgod February 2, 2022
Please note that this forum is for serious discussion of the protocol v0.4.0, do not discuss unrelated content in this forum, spam will be reported and blacklisted on GitHub.
Those who participate in meaningful discussions will be rewarded with a special POAP or NFT(RSS Fruit Token) to be used in future DAO. A separate email will be sent after v0.4.0 is released. Please ensure that the email is visible and available in your GitHub profile. For related queries please contact [email protected]
Let's get the adventure started!
We prepared a draft proposal v0.4.0 based on many problems encountered in the use of v0.3.1. But limited by the ability of a few people, the draft may contain many errors and poor design, which is the reason for the need for extensive participation in the discussion and this draft may differ significantly from the published version depending on the discussion and feedback.
URI
Inspired by Manifesto for Ubiquitous Linking and 让链接无处不在——《泛在链接宣言》的理论与理想, we have replaced a large number of id fields in the previous version with accessible URIs to make it easier for users to access the data.
These URIs meet the RFC 3986 specification, the scheme is rss3
, userinfo is the instance address and host is the account platform, e.g. evm solana flow.
type SignableAccount = string; // ${address}@${SignablePlatform}, for example, 0x1234567890123456789012345678901234567890@evm
type UnsignableAccount = string; // ${address}@${UnsignablePlatform}, for example, rss3_@twitter
type InstanceURI = string; // rss3://${SignableAccount}
type ItemURI = string; // ${InstanceURI}/${'notes' | 'assets'}/${uuid}
type ItemsPageListURI = string; // ${InstanceURI}/list/${'notes' | 'assets'}/page/${index}
type ItemsListURI = string; // ${InstanceURI}/list/${'notes' | 'assets'}
type LinksListURI = string; // ${InstanceURI}/list/links/${InstanceURI | NoteURI | AssetURI}/${index}
type BacklinksListURI = string; // ${InstanceURI}/list/backlinks/${URI}
type URI = string; // Any uri
type URIs = URI[] | URI; // A series of uris pointing to accessible resources
File Base
Each file has a number of base fields, and the files are classified as signed or unsigned, signed files are used for user submitted and authorized files, unsigned files are used for files that are automatically indexed by the nodes of the RSS3 network
InstanceURI
ItemsPageListURI
ItemsListURI
LinksListURI
BacklinksListURI
five URIs point to RSS3 files, the ItemsPageListURI
and LinksListURI
are user-signed files, the index at the end is to facilitate file signing and paging, the first page is 0, the second page is 1... ItemsListURI
and BacklinksListURI
are unsigned files, generated by the nodes of the RSS3 network, and do not require signature verification
interface Base {
version: 'v0.4.0'; // Proposal version for current file. It should be like `rss3.io/version/v1.0.0`
identifier: InstanceURI | ItemsPageListURI | ItemsListURI | LinksListURI | BacklinksListURI;
date_created: string; // Specifies the created date in RFC 3339 format
date_updated: string; // Specifies the updated date in RFC 3339 format
}
interface SignedBase extends Base {
signature: string; // Signed by instance's private key, the signature message is JSON string sorted by key alphabet: `[RSS3] I am confirming the results of changes to my file ${identifier}: JSON.stringify(file, Object.keys(file).sort())`
agent?: {
pubkey: string[]; // A random ed25519 public key generated by the client
signature: string[]; // A signature signed by pubkey's private key, the message is the same as `signature`
authorization: string; // A signature signed by instance's private key, the message is `[RSS3] I am well aware that this APP (name: ${app}) can use the following agent instead of me (${InstanceURI}) to modify my files and I would like to authorize this agent (${pubkey})`
app: string; // Name of the app using this agent, eg: Revery
}[];
}
interface UnsignedBase extends Base {
auto: true;
}
Index File
The Index file is the entry for each RSS3 instance and is the most important file.
The standard and implementation of controller
is uncertain and it is a reserved field.
profile
defines the information about the instance itself, the accounts
field is used to bind other accounts, both centralised and decentralised, e.g. evm solana twitter playstation; the banner
websites
field has been added.
links
defines the relationship between the current instance and any other URI, e.g. defining a relationship called following, its list can contain other RSS3 instance, an RSS address, or an RSS3 Note; identifier_back
is the reverse relationship, i.e. the relationship that other URI point to the current instance.
items
is the most important field, and the one we consider most and least certain; notes (the name derives from Misskey, previously called items) are used for the feed, identifier_page
contains the dynamics of the user's own posting, confirmed by the user's signature, such as a blog post or a message, and identifier additionally contains the dynamics automatically indexed by the nodes of the RSS3 network, such as the acquisition of an NFT; assets are assets owned by the instance, such as an NFT or a trophy won in PlayStation
interface Index extends SignedBase {
identifier: InstanceURI;
controller?: string; // A contract address indicating ownership of the file
profile?: {
name?: string;
avatar?: URIs;
bio?: string;
banner?: URIs;
websites?: URIs;
accounts?: ({
account: SignableAccount;
signature: string; // Signature of `[RSS3] I am adding ${SignableAccount} to my RSS3 instance ${InstanceURI}`
} | UnsignableAccount)[];
};
links: {
identifiers?: LinksListURI[];
identifier_back: BacklinksListURI;
};
items: {
notes: {
identifier_page?: ItemsPageListURI;
identifier: ItemsListURI;
};
assets: {
identifier_page?: ItemsPageListURI;
identifier: ItemsListURI;
};
};
}
Items
Items
is the biggest change apart from the URI.
Previous versions of items have been renamed notes
and previous versions of items+assets have been combined as items
.
notes
and assets
have the same format
links
of items
are in the same format as links
of instances
contents in the previous version renamed to attachments
to record resources such as images attached to notes
or assets
.
metadata
added to standardise the content indexed by the nodes of the RSS3 network.
type Item = {
identifier: ItemURI;
date_created: string; // Specifies the published date in RFC 3339 format
date_updated: string; // Specifies the modified date in RFC 3339 format
links: {
identifier_back: BacklinksListURI;
identifiers?: LinksListURI[];
};
tags?: string[];
authors?: InstanceURI[];
title?: string;
summary?: string;
attachments?: {
content: URIs;
mime_type: string; // [MIME type](https://en.wikipedia.org/wiki/Media_type)
name?: string;
size_in_bytes?: string;
}[];
metadata?: {
proof: string; // transaction, url, etc.
type: AutoAssetType | AutoNoteType;
from?: string;
to?: string;
id: string; // unique id, eg: ${token_address}-${token_id}
}
auto?: true; // For auto items
};
List Files
The format of the list file is simple and has not been changed significantly.
interface ListBase<URIType, ElementType> {
identifier: URIType;
identifier_next?: URIType;
list?: ElementType[];
}
type ItemPageList = SignedBase & ListBase<ItemsPageListURI, Item>;
type ItemsList = UnsignedBase & ListBase<ItemsListURI, Item>;
type LinksList = SignedBase & ListBase<LinksListURI, URI>;
type BacklinksList = UnsignedBase & ListBase<BacklinksListURI, InstanceURI | ItemURI>;
Overall
// word lists
type SignablePlatform = 'evm' | 'solana' | 'flow';
type UnsignablePlatform = 'twitter' | 'misskey' | 'jike';
type LinkType = 'following' | 'comment' | 'like' | 'collection';
type AutoAssetType = 'evm_gitcoin_donation' | 'evm_xdai_poap' | 'evm_bsc_nft' | 'evm_ethereum_nft' | 'evm_polygon_nft';
type AutoNoteType = AutoAssetType | 'evm_mirror_entry' | 'twitter_tweet' | 'misskey_note' | 'jike_node';
// unique id
type SignableAccount = string; // ${address}@${SignablePlatform}, for example, 0x1234567890123456789012345678901234567890@evm
type UnsignableAccount = string; // ${address}@${UnsignablePlatform}, for example, rss3_@twitter
// uri
type InstanceURI = string; // rss3://${SignableAccount}
type ItemURI = string; // ${InstanceURI}/${'notes' | 'assets'}/${uuid}
type ItemsPageListURI = string; // ${InstanceURI}/list/${'notes' | 'assets'}/page/${index}
type ItemsListURI = string; // ${InstanceURI}/list/${'notes' | 'assets'}
type LinksListURI = string; // ${InstanceURI}/list/links/${InstanceURI | NoteURI | AssetURI}/${index}
type BacklinksListURI = string; // ${InstanceURI}/list/backlinks/${URI}
type URI = string; // Any uri
type URIs = URI[] | URI; // A series of uris pointing to accessible resources
// Common attributes for each files
interface Base {
version: 'v0.4.0'; // Proposal version for current file. It should be like `rss3.io/version/v1.0.0`
identifier: InstanceURI | ItemsPageListURI | ItemsListURI | LinksListURI | BacklinksListURI;
date_created: string; // Specifies the created date in RFC 3339 format
date_updated: string; // Specifies the updated date in RFC 3339 format
}
interface SignedBase extends Base {
signature: string; // Signed by instance's private key, the signature message is JSON string sorted by key alphabet: `[RSS3] I am confirming the results of changes to my file ${identifier}: JSON.stringify(file, Object.keys(file).sort())`
agent?: {
pubkey: string[]; // A random ed25519 public key generated by the client
signature: string[]; // A signature signed by pubkey's private key, the message is the same as `signature`
authorization: string; // A signature signed by instance's private key, the message is `[RSS3] I am well aware that this APP (name: ${app}) can use the following agent instead of me (${InstanceURI}) to modify my files and I would like to authorize this agent (${pubkey})`
app: string; // Name of the app using this agent, eg: Revery
}[];
}
interface UnsignedBase extends Base {
auto: true;
}
// RSS3 index files, main entrance for a instance
interface Index extends SignedBase {
identifier: InstanceURI;
controller?: string; // A contract address indicating ownership of the file
profile?: {
name?: string;
avatar?: URIs;
bio?: string;
banner?: URIs;
websites?: URIs;
accounts?: ({
account: SignableAccount;
signature: string; // Signature of `[RSS3] I am adding ${SignableAccount} to my RSS3 instance ${InstanceURI}`
} | UnsignableAccount)[];
};
links: {
identifiers?: LinksListURI[];
identifier_back: BacklinksListURI;
};
items: {
notes: {
identifier_page?: ItemsPageListURI;
identifier: ItemsListURI;
};
assets: {
identifier_page?: ItemsPageListURI;
identifier: ItemsListURI;
};
};
}
// items
type Item = {
identifier: ItemURI;
date_created: string; // Specifies the published date in RFC 3339 format
date_updated: string; // Specifies the modified date in RFC 3339 format
links: {
identifier_back: BacklinksListURI;
identifiers?: LinksListURI[];
};
tags?: string[];
authors?: InstanceURI[];
title?: string;
summary?: string;
attachments?: {
content: URIs;
mime_type: string; // [MIME type](https://en.wikipedia.org/wiki/Media_type)
name?: string;
size_in_bytes?: string;
}[];
metadata?: {
proof: string; // transaction, url, etc.
type: AutoAssetType | AutoNoteType;
from?: string;
to?: string;
id: string; // unique id, eg: ${token_address}-${token_id}
}
auto?: true; // For auto items
};
// RSS3 list files
interface ListBase<URIType, ElementType> {
identifier: URIType;
identifier_next?: URIType;
list?: ElementType[];
}
type ItemPageList = SignedBase & ListBase<ItemsPageListURI, Item>;
type ItemsList = UnsignedBase & ListBase<ItemsListURI, Item>;
type LinksList = SignedBase & ListBase<LinksListURI, URI>;
type BacklinksList = UnsignedBase & ListBase<BacklinksListURI, InstanceURI | ItemURI>;
Edited By NaturalSelectionLabs