I put my identity-depth scorer behind a public GET endpoint so you can argue with it

작성자

카테고리:

← 피드로
DEV Community · Zeke · 2026-08-17 개발(SW)

Zeke

I have been building a thing I call depth-of-identity: instead of asking an account who are you (credentials, KYC, a captcha), you measure what it has done and how hard that history would be to fake. Chains of work, social reciprocity, money that actually moved. The bet is that behavior across several independent dimensions is exponentially more expensive to counterfeit than any single number like follower count.

I wrote a companion post about one narrow slice of this — gap-entropy, telling scheduled bots from humans purely by when they post. This post is about the other half: I took the aggregate scorer, the thing that rolls several dimensions into one weight, and hung it off a plain read-only endpoint. You can curl it. I want people to curl it and tell me where it is wrong.

The endpoint

GET https://captcha.powforge.dev/api/depth-check?pubkey=<64-hex or npub1...>

Enter fullscreen mode Exit fullscreen mode

No auth, no body, no cost. It accepts either a raw 64-char hex pubkey or an npub1.... Give it garbage and it tells you:

{"error":"invalid or missing pubkey (64-hex or npub1...)"}

Enter fullscreen mode Exit fullscreen mode

Give it a real pubkey and you get the full breakdown. Here is a real response, trimmed to the scores (every account has the four dimensions; each carries a pile of sub-metrics I left in the live response). This is fiatjaf’s pubkey, so you can reproduce it yourself:

GET /api/depth-check?pubkey=3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d

Enter fullscreen mode Exit fullscreen mode

{
  "pubkey": "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
  "depth": 307,
  "threshold": 100,
  "would_skip": true,
  "gating_active": false,
  "active_dimensions": 2,
  "total_events": 834,
  "account_age_days": 564,
  "dimensions": {
    "social":   { "score": 142, "reciprocityRatio": 0.268, "bidirectionalPeers": 38 },
    "access":   { "score": 0,   "totalPowBits": ...,        "maxDifficulty": ... },
    "vouch":    { "score": 0,   "inboundVouches": ...,      "cycleDropped": ... },
    "economic": { "score": 114, "inboundZaps": 510,         "genuineSenders": 276 }
  },
  "note": "diagnostic only — CAPTCHA gating is not affected by this score"
}

Enter fullscreen mode Exit fullscreen mode

Those are live numbers from scoring a long-lived, active pubkey (834 events, 564 days old). It cleared the threshold of 100 on two dimensions alone — social and economic — without any proof-of-work or vouch history. That is the whole point of the design: you do not need to max one axis, you need genuine breadth.

What the four dimensions mean

  • social — not follower count. It looks at reciprocity: how many peers reference you back versus the ones you only shout at. A thousand inbound mentions from accounts you never engage is worth far less than a hundred bidirectional conversations.
  • access — proof-of-work you have actually spent. Bits of difficulty on your events, log2-scaled so one heroic grind cannot hijack the whole score (I learned that the hard way; an early version let a PoW farm out-score real humans 15-to-1 until I capped per-dimension contribution).
  • vouch — inbound vouches from other identities, with cycles dropped so a ring of sockpuppets vouching for each other collapses to near nothing.
  • economic — zaps, deduplicated by the underlying Lightning invoice so you cannot inflate by re-broadcasting the same payment. It weighs genuine reciprocal senders over one-directional spray.

The depth weight is the additive roll-up. active_dimensions counts how many axes are non-zero, which matters more than the raw sum — a Sybil can farm one dimension, but farming three independent ones at once is where the cost explodes.

The corpus caveat

Here is the part product pages leave out. A depth score is only as good as the events behind it. The scorer can only weigh history it can actually see, so the endpoint fans out across public relays — right now wss://relay.damus.io, wss://nos.lol, and the powforge relay — and unions what they return. If none of those relays has ever ingested a pubkey’s events, that pubkey scores a wall of zeros with would_skip: false. That does not mean the account is a bot. It means depth is relative to a corpus, and no corpus is the whole network.

That is not a bug I am hiding, it is the actual research question. Widen the relay set and a thin score fills in; a genuinely active account that was invisible to one relay shows up once another relay that knows it is in the pool. Honest deployment means telling you which events the number is built from, and letting you point at a pubkey the corpus underweights.

You do not need to run anything locally to check a score — just curl the endpoint:

curl "https://captcha.powforge.dev/api/depth-check?pubkey=3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"

Enter fullscreen mode Exit fullscreen mode

{ "depth": 307, "active_dimensions": 2, "total_events": 834, "would_skip": true }

Enter fullscreen mode Exit fullscreen mode

That pubkey clears the threshold across two active dimensions against the live relay set. Aim the same endpoint at a pubkey none of those relays has heard of and it scores 0 — same code, different corpus. Sit with that for a second — it is the honest shape of every reputation system, most of them just do not show you the seam.

Why it does not gate anything

Notice gating_active: false and the note. This endpoint never blocks a captcha, never lets anyone skip a challenge, never touches the verify path. It is groundwork. Before I wire “skip the captcha if depth > threshold” into anything real, I want to watch the skip policy run against live traffic and see how often it would have been wrong — how many bots would have sailed through, how many humans it would have wrongly gated. Measure first, gate later, and let people poke holes while it is still only a diagnostic.

That is the invitation. Curl it against your own pubkey, against accounts you know are real, against accounts you know are bots, and if you find a pubkey where the score is obviously backwards, that is exactly the failure I want to hear about.

원문에서 계속 ↗