Social Graph Sybil Gate — Status and Design Blueprint¶
Status: Phase 1 core implemented, experimental. The issuer validates
SybilProof::SocialGraph, and theattester/crate provides signed-edge scoring, attestation issuance, and JWKS publication. The implementation is not proof-of-personhood or a production-complete trust system; this document records both the shipped core and the remaining design work. It was produced by parallel research (Freebird architecture, app signal survey, Sybil detection literature) followed by architectural design review.
Current implementation boundary¶
The issuer-side gate currently implements Cred-shaped presentation parsing and
verification, trusted local attester keys, Ed25519 signature checks, policy and
eligibility checks, time and request-binding checks, and replay protection. The
standalone attester implements POST /v1/attest,
GET /.well-known/jwks.json, and GET /health; it verifies signed Clout trust
edges and issues short-lived signed attestations.
The repository does not include the Cred proof agent or a Clout client. A
client/integration must obtain the attestation and construct the presentation
shape accepted by the issuer. SOCIAL_GRAPH_JWKS_URL refresh and persistent
revocation state are configured surfaces but are not implemented yet: local
attester keys remain authoritative and SOCIAL_GRAPH_STATE_PATH is not a
persistent revocation store. The current reference attester also does not emit
quota_nullifier; requiring one therefore needs an attester that supplies it.
1. Overview¶
The social_graph Sybil gate admits users based on reputation in an
external social/trust graph, primarily Clout.
Its purpose is to raise the cost of fake-account farming beyond what a
single invitation code, proof-of-work nonce, or rate-limit identity can
provide.
What problems this addresses¶
Freebird's current Sybil gates (invitation, pow, rate_limit,
webauthn, multi_party_vouching, progressive_trust) are all
point-in-time admission checks. None establish that a participant has
sustained, real-world social trust. A farmer who obtains one invitation
or solves one PoW challenge can request a token.
The social_graph gate consumes organic trust signals —
relationships that emerge from real social interaction, economic
activity, and civic participation over time. These signals are harder
to farm because they require sustained participation that decays if
neglected.
Core principle¶
Freebird's issuer verifies "this requester has a valid Cred presentation containing a social-graph eligibility attestation," not "this Clout identity has these graph edges."
The issuer must not ingest raw trust edges, invitation chains, wallet histories, ballot histories, or rendezvous participation data. Graph analysis happens in a separate Social Graph Attester service, and the attestation is held and presented by Cred (the user-owned proof agent). The issuer receives only a Cred presentation containing a signed attestation.
What it is not¶
- Not proof-of-personhood (graph reputation is gameable with patience)
- Not universal bot detection (no continuous behavioral analysis)
- Not a replacement for existing gates (it composes with them via
combinedmode)
It is a higher-cost admission layer that raises the farming bar by requiring real, aged, multi-signal social participation.
2. Architecture¶
Cred-mediated attestation flow¶
Graph analysis happens in a separate Social Graph Attester service, and the attestation is held and presented by Cred (the user-owned proof agent). This creates two privacy boundaries: attester → Cred, and Cred → Freebird issuer.
Client Cred (user agent) Social Graph Attester Freebird Issuer
│ │ │ │
│── 1. request ─→│ │ │
│ issuance │ │ │
│ │── 2. get request binding ──────────────────→│
│ │←── request_binding ─────────────────────────│
│ │ │ │
│── 3. ask Cred │ │ │
│ for social │ │ │
│ graph proof │ │ │
│ │── 4. request attestation ─────────────────→│
│ │ (Cred controller key, │
│ │ Clout trust evidence) │
│ │ │ │
│ │ 5. evaluate graph │
│ │ (SybilRank/heuristic) │
│ │ │ │
│ │←── 6. signed attestation ──────────────────│
│ │ (NOT request-bound; │
│ │ bound to Cred controller key) │
│ │ │ │
│ │── 7. store as cred.artifact_record │
│ │ │ │
│ │── 8. create cred.presentation │
│ │ bound to Freebird app_id + request_id │
│ │ (request_binding_hash embedded here) │
│ │ │ │
│←── 9. Cred presentation ─│ │ │
│ │ │ │
│── 10. submit as SybilProof::SocialGraph ─────────────────→│
│ │ │ │
│ │ 11. issuer verifies: │
│ │ - attester signature │
│ │ - policy/version │
│ │ - expiry │
│ │ - Cred presentation sig │
│ │ - request binding match │
│ │ - eligibility threshold │
│ │ - replay store (jti) │
│ │ │ │
│←── 12. VOPRF evaluation (token issued) ──────────────────│
Why Cred in the middle?¶
Cred is the user-owned proof agent
that holds keys, credentials, attestations, and app permissions locally.
It already has adapters for Freebird (check/verify), Witness
(attestations), and Matchlock (commitments/nullifiers), following a
canonical sophia/v1 contract with cred.permission_grant,
cred.action_request, and cred.presentation artifacts.
Routing the social graph attestation through Cred provides three privacy properties that direct client → attester → issuer does not:
-
The attester doesn't know which Freebird instance the user is targeting. The attester issues a general-purpose eligibility attestation bound to Cred's controller key. Cred later binds the presentation to a specific Freebird issuer's
request_idat presentation time. The attester never sees the request binding. -
Permission grants enforce the presentation boundary. Cred's
cred.permission_grantsystem constrains which apps can request which artifacts, withallowed_audiences,max_uses,expires_at, andhuman_approval: "per_use". A social graph grant would constrain presentation to specific Freebird issuers with single-use enforcement. -
The attestation is a canonical Sophia artifact. It follows the
sophia/v1contract withcontract_version,artifact_type, and canonical JSON serialization. This makes it testable via SophiaDOS conformance checks and smoke harnesses.
Why not issuer-side graph analysis?¶
Issuer-side analysis would require the issuer to see Clout public keys, trust edges, invitation chains, or browser-local graph snapshots. This breaks Clout's "Dark Social Graph" property and creates a strong issuance-time identity record that could later be correlated.
The Clout browser-local graph problem¶
Clout's strongest trust graph lives in the browser (IndexedDB), not on a server. The attester cannot simply query a Clout API for a user's full graph. Options considered:
| Option | Approach | Verdict |
|---|---|---|
| A. Client submits graph snapshot to Freebird issuer | Client sends trust edges directly | Rejected — breaks Dark Social Graph, issuer sees raw graph |
| B. Clout exposes server-side attestation API | Clout server computes score, issues attestation | Preferred long-term — requires Clout API work |
| C. Separate graph indexer service | Indexer aggregates Clout signals, computes scores | Preferred Phase 2 — sensitive infrastructure |
| D. Cred submits verifiable evidence to attester | Cred presents signed trust edges to attester on behalf of user | Phase 1 approach — requires Clout edges to be signed |
Phase 1 approach (Option D): Cred submits cryptographically signed
Clout trust evidence (signed trust edges, signed invitation chain,
timestamps) to the attester on behalf of the user. The attester
validates the evidence, runs the scoring heuristic, and issues an
attestation to Cred's controller key. Cred stores it as a
cred.artifact_record and later presents it to Freebird.
Prerequisite: Clout trust records must be cryptographically self-authenticating (signed edges, signed invitations, verifiable timestamps). If they are not currently signed, that is a prerequisite before Phase 1 can ship.
3. Trait Integration¶
New SybilProof variant¶
pub enum SybilProof {
// ... existing variants ...
SocialGraph {
/// Compact signed attestation from a trusted Social Graph Attester
attestation: String,
/// Proof that the requester controls the holder secret/key
/// bound to the attestation
presentation: String,
},
// ...
}
Signed attestation payload¶
The attestation is a signed payload issued to Cred's controller key. It is not request-bound at issuance time — Cred binds it to a specific Freebird request at presentation time.
| Field | Purpose |
|---|---|
contract_version |
"sophia/v1" (canonical Sophia artifact) |
artifact_type |
"social_graph.attestation" |
version |
Attestation schema version |
attester_id |
Which attester issued this |
kid |
Key ID used to sign |
policy_id |
Which scoring policy was applied |
issued_at |
When the attestation was created |
expires_at |
When it expires (short-lived) |
eligibility_level |
Coarse score bucket (not exact score) |
quota_nullifier |
Optional epoch-scoped nullifier for quota |
jti |
Unique attestation ID (for replay prevention) |
holder_commitment |
Commitment to Cred controller's public key |
signature |
Attester's Ed25519 signature over all fields |
Must not contain: Clout public key, raw trust edges, invitation path, exact SybilRank score, wallet address, ballot/rendezvous identifiers, any stable user identifier, or any Freebird-specific request binding. The attestation is general-purpose; Cred makes it request-bound at presentation time.
Cred presentation¶
When presenting to Freebird, Cred creates a cred.presentation
artifact containing:
- The signed attestation (embedded or referenced)
app_id: the Freebird issuer identifierrequest_id: the Freebird issuance request IDrequest_binding_hash: hash of the Freebird request binding- Cred controller's signature over the presentation
This presentation is what the client submits as
SybilProof::SocialGraph.attestation. The presentation field of
the proof contains the Cred presentation signature.
Config struct¶
Environment variables:
| Variable | Purpose | Default |
|---|---|---|
SOCIAL_GRAPH_ATTESTERS_PATH |
Path to trusted attester key config | none (required) |
SOCIAL_GRAPH_JWKS_URL |
Reserved JWKS URL; refresh is not implemented | none |
SOCIAL_GRAPH_KEY_REFRESH_INTERVAL |
Reserved refresh interval; currently unused | 1h |
SOCIAL_GRAPH_MIN_LEVEL |
Minimum eligibility level to accept | 1 |
SOCIAL_GRAPH_ACCEPTED_POLICY_IDS |
Comma-separated accepted policy IDs | none (required) |
SOCIAL_GRAPH_ATTESTATION_MAX_AGE |
Maximum age of accepted attestations | 5m |
SOCIAL_GRAPH_CLOCK_SKEW_SECS |
Allowed clock skew | 30 |
SOCIAL_GRAPH_REQUIRE_REQUEST_BINDING |
Require request binding match | true |
SOCIAL_GRAPH_REQUIRE_QUOTA_NULLIFIER |
Require epoch-scoped quota | false |
SOCIAL_GRAPH_REPLAY_TTL |
Replay store TTL | 10m |
SOCIAL_GRAPH_STATE_PATH |
Reserved revocation-state path; persistence is not implemented | social_graph_state.json |
SOCIAL_GRAPH_FAIL_CLOSED |
Reject if attester keys unavailable | true |
State struct¶
The current issuer gate keeps the following in memory:
- Trusted attester public keys loaded from
SOCIAL_GRAPH_ATTESTERS_PATH - Accepted policy IDs
- Key-load timestamp
- An in-memory revoked-key set (not persisted)
The configured state path is not currently read or written. Persistent key rotation/revocation state is planned. The implementation does not persist graph records, Clout identities, score histories, or edge snapshots.
verify_with_context flow¶
- Require
SybilProof::SocialGraph - Parse the Cred presentation (contains the signed attestation + presentation metadata)
- Verify Cred controller's signature over the presentation
- Verify attester identity and key ID
- Verify attester's Ed25519 signature over the attestation
- Check
policy_idis in accepted list - Check
issued_at,expires_at, and max age - Check eligibility level >=
SOCIAL_GRAPH_MIN_LEVEL - Require
ctx.request_bindingwhen configured - Compare
hash(ctx.request_binding)to the presentation'srequest_binding_hash - Verify
holder_commitmentmatches the Cred controller key that signed the presentation - Use replay store:
mark_once("social_graph:jti", jti, ttl)
Combined mode¶
The gate composes with existing gates via combined mode:
| Mode | Use case | Security note |
|---|---|---|
combined_or |
social_graph OR invitation |
Only as strong as easiest mechanism |
combined_and |
social_graph AND pow |
Both must pass — stronger |
combined_threshold |
2 of 3 mechanisms | Flexible middle ground |
Recommended production posture:
- Low-value onboarding:
invitation OR social_graph - Higher-value issuance:
social_graph AND powor threshold mode - Never treat
invitationalone as equivalent to a strong social graph pass
Replay store¶
Replay keys:
- social_graph:jti:<attester_id>:<jti> (always)
- social_graph:quota:<attester_id>:<quota_nullifier> (if quota enabled)
TTL should not exceed the attestation expiry. Redis-backed replay store is required for clustered deployments.
4. Signal Sources¶
Clout (primary signal)¶
Clout's trust graph is the strongest available signal. It is structurally similar to BrightID's social graph, but emerges from real social interaction rather than dedicated verification rituals.
Usable signals: - Signed trust edges (who trusts whom, weight, timestamp) - Signed invitation chain (inviter → invitee) - Edge age and temporal decay - Edge weight (0.1–1.0) - Independent endorsers - Seed-rooted paths - Fanout behavior (how many people does each node trust?) - Day Pass delegation history
Privacy cost: High if raw edges leave the browser. Raw Clout graph data goes only to the dedicated attester, never to the Freebird issuer.
Scarcity (weak secondary signal)¶
Usable signals (coarse attestations only): - Wallet age bucket (e.g., "exists for >30 days") - Activity count bucket (e.g., "participated in >5 transfers") - "Has ongoing economic activity" boolean
Must not expose: Raw transfer history, token graph, nullifier gossip, balances, or wallet addresses to Freebird.
Prestige (excluded)¶
Per-person ballot participation breaks coercion resistance and unlinkability. Do not consume.
Rendezvous (excluded)¶
Cross-pool correlation breaks the core privacy model. Pseudonym rotation makes cross-pool linkage intentionally impossible. Do not consume.
5. Privacy Analysis¶
Does this preserve issuance-redemption unlinkability?¶
The core flow preserves this property when used as designed.
The issuer learns that a requester had a valid social-graph attestation at issuance time. Redemption remains unlinkable because the redemption token carries no graph identity or attestation metadata.
What the issuer learns¶
- A trusted attester approved this request
- Coarse eligibility level (bucket, not exact score)
- Policy version
- Attestation expiry
- Request binding match
- Optional epoch-scoped quota nullifier
What the issuer must not learn¶
- Clout public key
- Browser-local graph contents
- Trust edges or invitation path
- Exact graph score
- Wallet address or transfer history
- Ballot or rendezvous participation
- Stable cross-epoch social identity
Attester trust boundary¶
With Cred in the middle, the attester's knowledge is significantly reduced compared to direct client → attester → issuer flow:
What the attester learns (Phase 1): - Cred controller public key (not Clout identity directly, though Clout evidence is submitted on the user's behalf) - That the user is seeking social-graph eligibility - The graph evidence submitted (signed Clout trust edges)
What the attester does NOT learn: - Which Freebird issuer the user will present to - When the attestation will be used - The Freebird request binding - Whether the attestation was ever used at all
This is a stronger privacy property than direct attester → issuer flow. The attester issues a general-purpose eligibility attestation; Cred makes it request-bound at presentation time.
Stronger long-term design (Phase 3): - Blind signatures or BBS+ anonymous credentials (attester cannot link issuance to presentation even with Cred) - Privacy Pass-style issuance - Per-issuer/per-epoch unlinkable nullifiers - Multiple independent attesters
Full privacy-preserving graph analytics remains an open research problem. The practical design is separation of duties plus anonymous attestations, not ZK proof of global graph position.
6. Threat Model¶
Fake trust edges¶
Attackers create many fake Clout identities and mutually endorse them.
Countermeasures: - Require seed-rooted paths - Cap edge weight - Apply fanout penalties (high-outdegree nodes are less trustworthy) - Require minimum edge age - Require independent roots - Ignore fresh dense subgraphs
Collusion rings¶
A group of real or fake users create a dense endorsement cluster.
Countermeasures: - SybilRank-style propagation from trusted seeds - Community diversity requirements - Outbound trust budget per node - Anomaly detection for dense new clusters
Purchased invitations / bridge farming¶
Attackers buy endorsements from honest users or compromise weak bridges into the honest region.
Countermeasures: - Require multiple independent paths - Decay or penalize high-fanout endorsers - Delay the effect of new trust edges - Slash or downgrade endorsers linked to abuse - Cap blast radius per trusted node
Eclipse attacks¶
An attacker surrounds a victim or feeds the attester only attacker-controlled graph evidence.
Countermeasures: - Cross-check against known roots/indexes where possible - Reject isolated client-only snapshots - Require independent corroboration - Use key transparency or append-only logs for trust records
Whaling¶
Attackers compromise high-trust Clout nodes and use them to vouch many Sybils.
Countermeasures: - Per-voucher issuance caps - Anomaly detection on endorsement spikes - Delayed trust activation - Revocation - Hardware-backed protection for high-trust accounts - Blast-radius limits
Temporal decay¶
Decay helps because instant farming is less valuable. Older, stable relationships carry more weight.
Limits: - Patient attackers can farm aged accounts - Compromised aged accounts remain dangerous - Purchased aged accounts bypass freshness checks
Operator warning signs¶
Operators should monitor for: - Sudden increase in accepted social-graph attestations - One attester dominating eligibility - One seed or voucher creating many accepted users - Sharp score distribution shifts - High rejection due to stale keys or replay failures - Attestation API outages - Repeated quota-nullifier collisions - Privacy-sensitive fields appearing in logs
Comparison to existing invitation gate¶
| Property | invitation |
social_graph |
|---|---|---|
| Farming cost | Low (one invite code) | Higher (requires aged, diverse trust) |
| Complexity | Simple | Complex (external attester, graph analysis) |
| Privacy risk | Low (issuer sees invite code) | Medium (attester sees graph evidence) |
| Bootstrapping | Built-in | Requires invitation fallback |
| Operational burden | Low | Higher (attester service, key management) |
7. Bootstrapping¶
New users with no Clout trust history need a path in.
Recommended model¶
- Entry: Use existing
invitationgate as the bootstrap mechanism - Probation: New users get low initial privileges
- Accumulation: Users build Clout trust history over time
- Promotion: After enough aged, independent signals exist, promote to social-graph eligibility
A single invitation should not equal high-trust social-graph eligibility.
Minimum viable admission¶
One of: - Trusted invitation plus waiting period - Two independent aged trust edges - Seed-rooted path within limited depth - Low-risk progressive-trust history - Threshold combination of invitation + proof-of-work + time
Cold-start resolution¶
The cold-start problem is solved by separating concerns:
| Stage | Mechanism | Privilege level |
|---|---|---|
| Entry | Invitation or community bootstrap | Minimal |
| Promotion | Social graph reputation accumulated | Standard |
| High-value | Stronger threshold requiring graph maturity | Elevated |
8. Implementation Phases¶
Remaining Pre-Phase 1 integration work¶
The following design and external-integration work remains:
- Define attestation schema (fields, encoding, signature format)
- Define Cred
social_graphadapter contract (import + present) - Define SophiaDOS
schemas/social-graph-attestation.schema.json - Decide signing format: canonical JSON with Ed25519 signature
- Confirm Clout trust records are signed and independently verifiable
- Prototype Cred presentation with request binding
- Prototype replay handling
- Complete attester-side quota/nullifier handling
- Choose initial thresholds
- Test false positives/false negatives on sample graphs
- Define attester key rotation and revocation
- Document privacy boundary and logging rules
If a deployment's Clout source cannot produce verifiable trust evidence, it must not use the gate.
Update: Investigation confirmed Clout trust edges ARE signed with Ed25519 and are independently verifiable by a third party. The Phase 1 prerequisite is met. See resolved open question #1 below.
Phase 1: MVP (core implemented; experimental)¶
Implemented (Freebird):
- SybilProof::SocialGraph variant
- Issuer-side verifier gate (verifies Cred presentation + attester sig)
- Trusted attester key config from local JSON
- Replay-store integration
- Coarse eligibility levels
Implemented (Social Graph Attester): - Signed Clout-edge verification - Seed-rooted path and threshold scoring with temporal age and fanout limits - Signed short-lived attestation issuance - JWKS publication endpoint
External or deferred integration:
- social_graph adapter: import-attestation + present-attestation
- Permission grant type: social_graph.present
- Presentation binding to Freebird app_id + request_id +
request_binding_hash
The issuer accepts the resulting presentation shape and enforces its request binding, but the Cred adapter and user-agent custody model are outside this repository.
Deferred SophiaDOS integration:
- schemas/social-graph-attestation.schema.json
- scripts/run-social-graph-live-seam.sh smoke test
Signals: - Clout signed trust edges - Edge age - Edge weight - Independent endorsers
Algorithm: - Simple heuristic, not full SybilRank - Seed-rooted trust score - Temporal decay - Fanout caps - Minimum independent endorsements
Privacy: - Freebird issuer sees only Cred presentation + eligibility level - Attester sees the holder commitment + Clout evidence, but NOT which Freebird instance the user will present to - Cred enforces per-use human approval before presentation
Limitations: - Attester is trusted (sees graph evidence) - No full privacy-preserving graph analytics - Issuer JWKS URL refresh and persistent revocation state are not implemented - The reference attester does not enforce identity quotas or emit quota nullifiers - Collusion and bridge farming remain possible - Heuristic thresholds require tuning
Phase 2: Stronger graph scoring¶
Build: - Opt-in graph indexer or Clout-hosted attestation API - Periodic SybilRank / personalized PageRank computation - Community diversity scoring - Abuse feedback loop - Attester revocation and policy versioning - Optional coarse Scarcity participation attestations
Signals: - Larger Clout graph - Signed trust edges - Invitation roots - Edge age/decay - Coarse wallet activity attestations
Privacy: - Issuer still sees only attestations - Attester/indexer sees more graph data (preferably opt-in and minimized)
Limitations: - Seed bias - Governance complexity - Graph indexer becomes sensitive infrastructure
Phase 3: Full vision¶
Build: - Anonymous credential issuance (BBS+ or similar) - Blind attestations - Per-issuer/per-epoch unlinkable nullifiers - Multiple independent attesters - Audited policy engine - Robust revocation - Community-local scoring - Optional stake/time/activity hybrid model
Signals: - Clout primary - Scarcity only as coarse privacy-preserving attestations - No raw Prestige or Rendezvous signals
Privacy: - Issuer cannot identify graph participant - Attester ideally cannot link credential issuance to Freebird presentation - Redemption remains unlinkable
Limitations: - Fully private global Sybil detection is still an open research problem - Practical system still depends on trusted seeds, governance, and monitoring
9. Open Questions¶
- ~~Are Clout trust edges currently signed and independently verifiable?~~
Resolved: Yes. Clout trust edges are signed with Ed25519 over a
canonical payload hash (truster, trustee, weight, timestamp, revoked).
Both plaintext and encrypted trust signals carry signatures. Timestamps
are bound into the signature and backed by Witness attestations. A
third-party attester can independently verify trust edges without Clout
being present. Invitation codes are NOT currently signed by the inviter
— this is a non-blocking gap that could be addressed in a future Clout
change to strengthen the invitation chain signal. See
clout/src/trust/plaintext-signal.ts:18-52andclout/src/crypto.ts:614-744. - ~~Who operates the Social Graph Attester?~~ Confirmed: Same operator as the Freebird issuer for Phase 1. This is simplest, keeps trust concentrated in one party the deployer already trusts, and avoids multi-party attester governance complexity. Phase 3 targets multiple independent attesters for stronger trust distribution.
- ~~Is the attester allowed to know the user is requesting Freebird eligibility?~~ Resolved for the shipped protocol: the attester is not given the Freebird request binding. The reference attester receives a holder commitment, subject, and signed graph evidence; it does not receive a Freebird request ID or binding hash. The Cred-shaped presentation binds the attestation to the Freebird request, and the issuer checks that binding. The attester can still know that its attestation may be used for Freebird eligibility from deployment context. Phase 3 targets blind attestations to reduce that knowledge further.
- ~~Should quota be enforced by the attester only, or also via
issuer-visible epoch nullifiers?~~
Partially resolved in the shipped implementation. The issuer can
optionally check
quota_nullifierthrough the replay store, controlled bySOCIAL_GRAPH_REQUIRE_QUOTA_NULLIFIER. The reference attester currently emits no quota nullifier and does not enforce a per-identity epoch quota, so a deployment requiring that defense must provide an attester that does. - ~~What is the minimum acceptable eligibility threshold for Phase 1?~~ Confirmed: Conservative starting values:
- At least 2 independent trust edges from distinct Clout identities
- Edge age > 7 days (prevents instant farming)
- Minimum weighted trust score of 0.3 (on Clout's 0.1–1.0 scale)
- At least 1 seed-rooted path (connected to the invitation tree root)
- Fanout cap: endorsers with >20 outbound trust edges get discounted
These are deliberately conservative — they'll reject most farmers
while accepting genuine community members. They'll need tuning with
real graph data during Pre-Phase 1 prototyping.
6. ~~How are attester keys rotated and revoked?~~
Partially implemented. The reference attester publishes its current
Ed25519 public key at a JWKS endpoint, but the issuer currently loads
trusted keys from SOCIAL_GRAPH_ATTESTERS_PATH;
SOCIAL_GRAPH_JWKS_URL refresh, durable revocation, and automated
rotation are not implemented. Operators must change the local trusted-key
configuration and coordinate key retirement manually until that lifecycle
is added.
7. ~~What abuse feedback can Freebird safely send back without
deanonymizing redeemers?~~
Resolved (technical): Very little, by design.
- The issuer can publish aggregate statistics: attestation
acceptance/rejection counts, attester ID distribution, policy ID
distribution. These are safe because they don't link to individual
users.
- The issuer must NOT send per-user feedback to the attester. Any
feedback channel from issuer to attester about specific
attestations (jti, holder commitment, request binding) would
create a correlation path between Freebird issuance and the
attester's Clout identity records.
- The attester should detect abuse through its own graph analysis
(dense new clusters, endorsement spikes, etc.), not through issuer
feedback.
- If abuse is detected (e.g., a farmed cluster), the attester
revokes eligibility for those Clout identities at the attester
level. The issuer doesn't need to know why.
8. ~~What fields are safe to log?~~
Resolved (technical): Different rules for issuer vs. attester.
Issuer-side (safe at INFO level):
- attester_id, policy_id, eligibility_level (bucket)
- jti (for replay debugging — rotate logs frequently)
- request_binding_hash (not the binding itself)
- timestamp, accept/reject decision
- reject reason (generic: "expired", "bad signature", "replay",
"below threshold")
Issuer-side (must NOT log): - Clout public key - Graph data (edges, scores, invitation chains) - Exact SybilRank score - Holder commitment (unless DEBUG level with short retention) - Full attestation payload
Attester-side (safe to log, but more sensitive):
- Clout identity, evidence submitted, score computed, attestation
issued (jti, expiry)
- These logs need their own retention policy and access controls.
9. ~~Should different Freebird issuance classes require different
social-graph levels?~~
Confirmed: Yes. The gate supports this via SOCIAL_GRAPH_MIN_LEVEL
config. Starting classes:
- Low-value onboarding (e.g., basic Clout posting): level >= 1
- Standard issuance (e.g., Scarcity transfers): level >= 2
- High-value issuance (e.g., Prestige ballot creation): level >= 3
Different Freebird instances can be configured with different thresholds. The specific classes and levels are the operator's policy decision. 10. ~~What is the governance process for trusted seeds and policy changes?~~ Confirmed: Phased approach. - Phase 1: Single operator decides. The operator configures trusted seeds and policy IDs via environment variables. Changes require restarting the issuer with new config. - Phase 2: Community vote via Prestige (uses existing infrastructure in the ecosystem). - Phase 3: Multi-party threshold approval (most robust, most complex).
Research basis¶
This blueprint was produced by three parallel research lanes, followed by architectural design review, followed by Cred/SophiaDOS integration:
- Freebird architecture review —
SybilResistancetrait, existing gates, combiners, replay store, persistence patterns, startup wiring - App signal survey — Clout, Scarcity, Prestige, Rendezvous trust signals, data structures, queryability, privacy costs
- Sybil detection literature — SybilGuard, SybilLimit, SumUp, SybilInfer, SybilRank, BrightID/Aura, privacy-preserving graph analysis, attack taxonomy, bootstrapping strategies
- Cred + SophiaDOS review — user agent custody/presentation model,
sophia/v1canonical contract, permission grants, existing adapter pattern (Freebird/Witness/Matchlock), smoke harness integration
Key findings that shaped the design:
- SybilRank is the practical baseline for seed-based trust propagation, but pure graph topology is insufficient. Multi-signal scoring (graph + temporal + economic) is stronger.
- Privacy-preserving full-graph Sybil detection is an open research problem. The practical resolution is separation of duties: graph analysis at a dedicated attester, anonymous attestation to the issuer, unlinkable redemption.
- Clout is the only viable primary signal source. Its trust graph is structurally similar to BrightID's, but emerges from real social interaction. Scarcity can contribute weak secondary signals. Prestige and Rendezvous cannot be consumed without breaking their own privacy models.
- The attester pattern follows Freebird's existing architecture: the issuer verifies a proof, it does not perform the underlying computation. Just as the issuer verifies a PoW nonce without mining it, the issuer verifies a social-graph attestation without computing the graph score.
- Cred mediation strengthens the privacy boundary: the attester issues a general-purpose eligibility attestation to Cred's controller key without knowing which Freebird instance the user will present to. Cred binds the presentation to a specific Freebird request at presentation time, enforcing per-use human approval and permission grant constraints.
- SophiaDOS provides the canonical contract layer: the attestation
is a
sophia/v1artifact with a JSON Schema, conformance checks, and a smoke harness seam that validates the full attester → Cred → Freebird flow end-to-end.