glowrm

Trust infrastructure for ATProto social applications

What is Glowrm?

Glowrm is trust infrastructure for ATProto social applications. Think of it as Stripe for reputation - instead of each dating app, professional network, or friendship platform building its own trust and moderation systems, apps plug into Glowrm to share a common reputation layer.

What Glowrm Provides

Cross-app Reputation

User trust scores (20-80 scale) that travel between apps. Good behavior on a dating app means you start with that same reputation on a professional network.

Shared Moderation

When someone gets reported on one app, it affects their reputation across the network. Prevents bad actors from platform-hopping.

Resource Allocation (SPA)

Configurable systems that limit how many people users can contact per time period. Prevents spam, encourages intentional interactions.

Identity Registry

Maps ATProto DIDs to apps, tracks verification status, enables cross-app queries without apps storing each other's user data.

What Glowrm Is NOT

The One-Line Pitch: "Portable identity (ATProto) needs portable reputation. Glowrm makes trust travel with users."

The Problem

Decentralized Identity Creates a Trust Gap

ATProto gives users portable identity:

But portability has a dark side:

Traditional platforms solve this with centralized control:

Glowrm enables both: Users keep freedom to move between apps, but reputation follows them. Accountability without platform lock-in.

Why Apps Need Shared Infrastructure

Building trust systems is hard:

Glowrm provides shared infrastructure:

How Glowrm Works

Data Flow Example

Let's trace what happens when someone uses two apps powered by Glowrm:

1. Alice joins PBJ (dating app)

Alice -> PBJ: Signs in with ATProto
PBJ -> Glowrm: "Register did:plc:alice123 in app 'pbj'"
Glowrm:
  - Creates identity record
  - Sets reputation: 50 (new recruit)
  - Initializes SPA: 15 jars/week
  - Returns: { reputation: 50, jars: 15 }

2. Alice sends jars to Bob

Alice -> PBJ: Sends 5 jars to Bob
PBJ -> Glowrm: "Use 5 units for did:plc:alice123"
Glowrm:
  - Checks: Does Alice have 5 jars? Yes (15 available)
  - Deducts 5 from her balance
  - Records allocation
  - Returns: { remaining: 10 }

3. Bob and Alice match

PBJ -> Glowrm: "Report positive_interaction"
Glowrm:
  - Creates trust event (type: positive)
  - Updates both reputations: +1
  - Alice: 50 -> 51
  - Bob: 50 -> 51

4. Alice reports Bob for harassment

Alice -> PBJ: Reports Bob
PBJ -> Glowrm: "Trust event - report, severity: high"
Glowrm:
  - Creates trust event
  - Decreases Bob's reputation: 51 -> 48
  - Flags for admin review

5. Bob gets banned on PBJ

Admin -> Glowrm: Ban did:plc:bob456 (global)
Glowrm:
  - Updates Bob's reputation: 48 -> 20
  - Marks status: banned
  - Global flag: affects all apps

6. Bob tries to join Roster (professional network)

Bob -> Roster: Signs in with ATProto
Roster -> Glowrm: "Register did:plc:bob456 in app 'roster'"
Glowrm:
  - Finds existing identity
  - Checks reputation: 20 (banned)
  - Returns: { reputation: 20, status: "banned" }
Roster -> Bob: "Cannot join - account flagged"

7. Meanwhile, Alice joins Roster

Alice -> Roster: Signs in
Roster -> Glowrm: "Register did:plc:alice123"
Glowrm:
  - Finds existing identity
  - Returns: { reputation: 51, status: "active" }
Roster: Shows Alice as trusted user
Key insight: Alice's good behavior on PBJ gave her a head start on Roster. Bob's bad behavior on PBJ prevented him from joining Roster. Neither app had to build this coordination - Glowrm handled it.

Core Concepts

1. Reputation Scores (20-80 Scale)

Why 20-80? Inspired by baseball scouting grades. 50 is average, scores cluster around the middle, outliers at the extremes are rare and meaningful.

Score Range Status Description
70-80 Exceptional Consistently positive interactions, helpful, responsive
60-69 Above Average Good track record, few issues
50-59 Average Normal range for new or moderately active users
40-49 Below Average Some negative events, approaching problematic
30-39 Poor Multiple reports, blocks, or suspicious patterns
20-29 Critical Banned or serial bad actor

Power Protection

Reputation is designed to be hard to game:

2. Trust Events

Types

Impact on Reputation

Event Type Impact
Positive interaction+1 (max +15 from this source)
Report (low)-1
Report (medium)-2
Report (high)-3
Block-3
BanSets to 20

3. Strategic Profile Allocation (SPA)

The problem SPA solves: Unlimited actions lead to spam. Tinder-style swiping creates a "spray and pray" approach. LinkedIn InMail becomes a sales pitch fire hose.

The solution: Give users finite "units" (jars, credits, picks, waves) per time period. Forces strategic choices.

Each App Configures

App Units Name Period Variable?
PBJ (dating) 15 jars 7 days Yes (1-10)
Roster (professional) 10 credits 30 days Yes (1-5)
Roomies (friendship) 20 waves 14 days No (only 1)
Key insight: Recipients see how many units you spent on them. Sending 5 jars says "I'm really interested." Sending 1 jar says "Maybe, let's see."

4. Identity & Verification

DIDs as Primary Identifier

Privacy

Architecture

System Components

+----------------------------------------------+ | User's Device | | +----------------------------------------+ | | | PBJ App (Dating) | | | | or Roster (Professional) | | | | or Roomies (Friendship) | | | +----------------------------------------+ | +--------------------+-------------------------+ | | 1. ATProto Auth +------------------+ | | v v +-----------------+ +------------------+ | ATProto PDS | | User's Repo | | (Bluesky) | | (Profile Data) | +-----------------+ +------------------+ | | 2. App gets DID | v +---------------------------------+ | App's Backend | | (PBJ, Roster, Roomies) | | | | - Conversations | | - Matches | | - Local preferences | +---------------+-----------------+ | | 3. Trust/SPA calls | v +---------------------------------+ | GLOWRM | | (Trust Infrastructure) | | | | - Identity registry | | - Reputation scores | | - Trust events | | - SPA state | | - Unit allocations | +---------------------------------+

Data Separation

Data Type Location Who Controls
Profile (bio, photos) User's ATProto repo User
Conversations/messages Individual app DB App
Matches Individual app DB App
Reputation score Glowrm Glowrm
Trust events Glowrm Glowrm
Unit allocations Glowrm Glowrm
Verification status Glowrm Glowrm

Why this separation?

Integration Guide

Quick Start (5 Minutes)

1. Register your app

curl -X POST https://glowrm.io/v1/apps/register \
  -H "Content-Type: application/json" \
  -d '{
    "id": "my-app",
    "name": "My App",
    "displayName": "My App - Find Your People",
    "appType": "dating",
    "spaConfig": {
      "unitsTotal": 15,
      "allowVariableAmount": true,
      "unitName": "credit",
      "periodDays": 7
    }
  }'

Returns:

{
  "appId": "my-app",
  "apiKey": "glowrm_xxxxxxxxxxxxx"
}

2. Configure your environment

GLOWRM_API_URL=https://glowrm.io
GLOWRM_API_KEY=glowrm_xxxxxxxxxxxxx

3. Add to your auth flow

// After user logs in with ATProto
async function onUserLogin(atprotoSession) {
  const { did, handle } = atprotoSession;
  
  // Register with Glowrm
  const response = await fetch(
    `${GLOWRM_API_URL}/v1/identities/register`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${GLOWRM_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ did, handle, appId: 'my-app' })
    }
  );
  
  const userData = await response.json();
  // userData = { reputation: 50, spaState: {...} }
  
  return userData;
}

4. Check units before actions

async function getUserUnits(did) {
  const response = await fetch(
    `${GLOWRM_API_URL}/v1/spa/${did}/state?appId=my-app`,
    {
      headers: { 'Authorization': `Bearer ${GLOWRM_API_KEY}` }
    }
  );
  
  const spaState = await response.json();
  // { unitsRemaining: 12, unitsTotal: 15, periodEndsAt: "..." }
  
  return spaState;
}

5. Report interactions

async function reportMatch(userDid, matchedDid) {
  await fetch(`${GLOWRM_API_URL}/v1/trust/events`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${GLOWRM_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      subjectDid: matchedDid,
      actorDid: userDid,
      appId: 'my-app',
      type: 'positive_interaction',
      notes: 'Users matched'
    })
  });
}
That's it! Your app now has cross-app reputation, spam prevention (SPA), and shared moderation intelligence.

Best Practices

Report interactions proactively:

Display reputation tastefully:

// Don't show exact scores to users
// Instead, use ranges or indicators
function reputationBadge(score) {
  if (score >= 70) return { text: "Trusted", color: "green" };
  if (score >= 50) return { text: "Verified", color: "blue" };
  if (score >= 30) return { text: "New", color: "gray" };
  return { text: "Flagged", color: "red" };
}

Reference Implementations

PBJ (Dating App)

15 jars per week, variable amounts (1-10 jars). Bilateral exchange unlocks messaging. Recipients see how many jars you spent.

View PBJ Demo

Roster (Professional)

10 credits per month, variable amounts (1-5 credits). 1 credit = quick question, 5 credits = mentorship request.

View Roster Demo

Roomies (Roommate)

20 waves per 2 weeks, fixed amount (always 1 wave). Higher unit count because roommate search is often urgent.

Demo coming soon

FAQ

Q: Does Glowrm see my profile data?

No. Profile content (photos, bio, interests) lives in your ATProto repository. Apps read directly from your repo. Glowrm only tracks your DID, reputation score, and interaction history.

Q: Can I have different reputations on different apps?

No. Your reputation is cross-app intentionally. The whole point is that behavior on one platform affects others. This creates accountability.

Q: What if I get unfairly reported?

The reputation system is power-protected. One or two reports from new users barely affect your score. Multiple reports from trusted users matter more. Admins review high-severity events.

Q: Can I see why my reputation changed?

Apps can show you your recent trust events (matches, reports) but not detailed notes from other users (privacy). You know "reputation decreased due to report" but not exactly what was said.

Q: What happens if an app goes rogue and reports everyone?

Glowrm tracks per-app patterns. If one app suddenly reports 50% of users, that's flagged for admin review. Apps that abuse the system lose access.

Q: How do I appeal a ban?

Contact the app that banned you first. If it was a global ban, contact Glowrm directly. Provide context, explain what happened. Admins review and can adjust reputation or remove bans.

Q: Can I reset my reputation and start over?

No. The whole system is designed to prevent fresh starts after bad behavior. If you've genuinely changed, build reputation back up over time through positive interactions.