@latimer-woods-tech/reputation
v0.1.0
Published
Co-sign and earned standing: a sybil-resistant reputation model where an endorsement's weight comes from the signer's earned standing, never from a raw count.
Readme
@latimer-woods-tech/reputation
Co-sign and earned standing. A co-sign is a first-person, reputation-staked endorsement — your endorsement is the signal. Its weight comes from the signer's earned standing, never from a raw count.
Zero runtime dependencies, no Node built-ins — safe inside a Cloudflare Worker.
The problem
Counting endorsements is worthless. Anyone can register a hundred accounts and have them all endorse each other. Reputation that can be minted from nothing is not reputation.
The model
Standing is a personalised-PageRank / EigenTrust shape over the co-sign graph, and two properties carry the whole defence:
1. Standing originates outside the co-sign graph. Every actor has a base —
standing earned through costly, externally-verifiable activity (completed sales,
settled payouts, delivered licenses). This package does not decide what counts as
earned; you supply it. But it requires it:
If total base across all actors is zero, every standing is zero. A ring of fresh accounts endorsing each other in a closed loop produces exactly nothing, no matter how dense the ring.
2. A signer's influence divides by how much they spread it. Flow along an edge is
standing(signer) / outdegree(signer). Endorsing everyone dilutes each endorsement
toward nothing. Co-signing is staking, not stamping.
damping bounds how much standing can come from being endorsed rather than earning:
(1 - damping) of the mass stays anchored to the earned base. Lower damping = more
skeptical of endorsement.
Standing
import { computeStanding, standingOf } from '@latimer-woods-tech/reputation';
const scores = computeStanding({
actors: [
{ actor_id: 'producer-a', base: 48_00 }, // e.g. net payout cents — costly to fake
{ actor_id: 'newcomer', base: 0 },
],
cosigns: [{ signer_id: 'producer-a', subject_id: 'newcomer' }],
damping: 0.5,
});
standingOf(scores, 'newcomer'); // > 0 — an earner vouched for themDeterministic: same inputs, same scores. Self-edges, duplicates, and edges naming
unknown actors are sanitised out before iteration. Scores land in [0, 1], sorted
descending.
Co-signing
Storage-agnostic — inject persistence, exactly like @latimer-woods-tech/provenance.
import { recordCosign } from '@latimer-woods-tech/reputation';
const result = await recordCosign(
{ signer_id, subject_id, subject_kind: 'artist' },
{
hasCosigned: (s, x) => db.cosignExists(s, x),
standingOf: (s) => db.currentStanding(s),
save: (cosign) => db.insertCosign(cosign),
},
);
if (result.status === 'rejected') {
// 'self_cosign' | 'duplicate'
}Guards: no self-co-signing, no duplicates (endorsing twice does not endorse
harder). A recorded co-sign carries weight — the signer's standing at signing time.
weightis an audit record of what was staked, not the authority on current influence. Never rank by summingweight; rank by recomputing standing over the live graph.
What this does not defend against
An actor with real earned standing who chooses to endorse bad subjects. That is a policy problem (revocation, slashing), not a graph problem, and it is out of scope for v0.1. Standing is not a moral score — it measures earned economic participation and who the earners vouch for.
License
MIT © Latimer Woods Tech
