open-secrets-sdk
v0.1.3
Published
SDK for the Open Secrets protocol on Nostr
Maintainers
Readme
Open Secrets SDK
A decentralized protocol for anonymous confessions, built on Nostr.
Our Philosophy
Confession websites are ephemeral. They start empty, grow briefly, and eventually die, taking years of human secrets and community with them.
Open Secrets was created to end this cycle. By moving the "database" of secrets to a decentralized network (Nostr), we ensure that:
- Communities Never Die: If your favorite confession site goes offline, the data remains. A new client can spin up and instantly restore the entire community history.
- Global Repository: We are building a permanent, global archive of anonymous human experiences that no single entity owns or can delete.
- Cross-App discovery: A secret posted on one app can be discovered and discussed on another, creating a massive, interconnected network of anonymous talk.
Installation
npm install open-secrets-sdkUsage
Creating a Post
import { createOpenSecretsTags } from 'open-secrets-sdk';
const tags = createOpenSecretsTags({
lang: 'en',
gender: 'female',
age: 25,
country: 'US',
client: 'my-awesome-app'
});
// Use with nostr-tools to sign and publishParsing metadata
import { parseOpenSecretsTags } from 'open-secrets-sdk';
const metadata = parseOpenSecretsTags(event.tags);
console.log(metadata.gender); // 'female'Building a Client
The SDK provides an OpenSecrets class that handles the pool management and parsing for you.
Plug-and-Play Example
import { OpenSecrets } from 'open-secrets-sdk';
// 1. Initialize with your relays
const os = new OpenSecrets(['wss://nos.lol', 'wss://relay.damus.io']);
async function main() {
// 2. Fetch secrets (already parsed and tagged)
const secrets = await os.fetchSecrets(50);
// 3. Display and filter
secrets.forEach(s => {
console.log(`${s.meta.gender} from ${s.meta.country}: ${s.content}`);
});
// 4. Publish a new secret (creates and signs an ephemeral event)
await os.publishSecret("I love decentralized protocols", {
gender: 'male',
country: 'DE',
client: 'my-app'
});
}Moderation & Safety
The Decentralized Reality
Because Open Secrets is decentralized, no one can delete a post from the network once it is published. There is no central admin who can "wipe" undesirable content.
Client-Side Defense (The "Gatekeeper" Role)
As a client developer, you are the editor of your own app. You have the power (and responsibility) to decide what your users see.
Since you cannot censor the protocol, you must filter the view.
1. NSFW Handling
Always check the isNsfw flag on the metadata. You can choose to blur these posts or hide them entirely by default.
const postsToShow = allPosts.filter(p => !p.metadata.isNsfw);2. Content Removals (Reporting)
Since every post uses a fresh identity, blacklisting users is impossible. However, you can maintain a local list of problematic event.ids (e.g., from reports) to hide specific posts that violate your app's rules.
const REMOVED_IDS = ['event_id_1', 'event_id_2'];
const filteredPosts = posts.filter(p => !REMOVED_IDS.includes(p.id));3. Trust-Based Filtering (Client Allowlist)
If you want to be stricter, you can choose to only display posts that originated from "trusted" clients.
Note on Trusted Clients: Some client may use a "publish first, moderate later" approach to ensure a 100% censorship-resistant archive. This means a trusted client will still broadcast everything to Nostr, but will hide problematic posts in its own UI once its filters catch up. As a developer, you should always combine client trust with your own local filters.
const TRUSTED_CLIENTS = ['lapregunta', 'trusted-app-1'];
const verifiedPosts = posts.filter(p => TRUSTED_CLIENTS.includes(p.metadata.client));3. Content Filtering
Since it's anonymous text, you can run simple keyword filters before rendering the content to the user.
const BAD_WORDS = ['...'];
const safePosts = posts.filter(p => !BAD_WORDS.some(word => p.content.includes(word)));Protocol Details
Open Secrets uses Nostr Kind 1 events with specific tags:
#t:open-secrets(The gatekeeper tag)#l: Used for namespaced metadata (gender, age, country, lang, etc.)client: Identifies the originating application.content-warning: Standard Nostr tag for NSFW content.
License
MIT
