hardened bluesky app fork with microcosm
0

Configure Feed

Select the types of activity you want to include in your feed.

Reconstruct profile verification state from microcosm

Verifications are app.bsky.graph.verification records whose subject points at
the verified DID (a Constellation backlink); each record's repo is the issuer.
hydrateVerificationState fetches them, resolves issuer identity, and builds the
VerificationState now attached to hydrateProfile's ProfileViewDetailed.

isValid is computed per the lexicon: the handle captured in the record must
still match the subject's current handle. verifiedStatus is 'valid' if any
verification is valid.

Caveat: the AppView only surfaces verifications from a curated trusted-verifier
set, which is Bluesky policy not present in the records, so we include every
issuer. Verified against bsky.app (4/4 records valid, handle bsky.app).

+82
+2
src/lib/microcosm/constellation.ts
··· 90 90 followers: 'app.bsky.graph.follow:subject', 91 91 /** Membership records of a list (subject = list at-uri). */ 92 92 listItems: 'app.bsky.graph.listitem:list', 93 + /** Verifications issued for an identity (subject = verified DID). */ 94 + verifications: 'app.bsky.graph.verification:subject', 93 95 /** Blocks of an identity (subject = blocked DID). */ 94 96 blocks: 'app.bsky.graph.block:subject', 95 97 } as const
+80
src/lib/microcosm/hydrate.ts
··· 197 197 } 198 198 199 199 /** 200 + * Reconstruct a profile's `VerificationState` from microcosm. Verifications are 201 + * `app.bsky.graph.verification` records whose `subject` points at the verified 202 + * DID (a Constellation backlink); each record's repo is the issuer. 203 + * 204 + * NOTE on "trusted verifiers": the AppView only surfaces verifications from a 205 + * curated trusted-verifier set, which is Bluesky policy not present in the 206 + * records, so we can't reproduce that filter. We include every issuer and let 207 + * the UI decide. `isValid` is computed structurally: the handle captured in the 208 + * record must still match the subject's current handle (per the lexicon). 209 + */ 210 + async function hydrateVerificationState( 211 + did: string, 212 + currentHandle: string, 213 + signal?: AbortSignal, 214 + ): Promise<AppBskyActorDefs.VerificationState | undefined> { 215 + const page = await constellation 216 + .getBacklinks( 217 + { 218 + subject: did, 219 + source: constellation.Sources.verifications, 220 + limit: 20, 221 + }, 222 + signal, 223 + ) 224 + .catch(() => undefined) 225 + if (!page || page.records.length === 0) return undefined 226 + 227 + const verifications = ( 228 + await Promise.all( 229 + page.records.map( 230 + async (ref): Promise<AppBskyActorDefs.VerificationView | undefined> => { 231 + const uri = `at://${ref.did}/${ref.collection}/${ref.rkey}` 232 + const rec = await getRecordByUri(uri, undefined, signal).catch( 233 + () => undefined, 234 + ) 235 + if (!rec) return undefined 236 + const value = rec.value as { 237 + handle?: string 238 + createdAt?: string 239 + } 240 + // Resolve the issuer's current identity for display. 241 + const issuer = await resolveMiniDoc(ref.did, signal).catch( 242 + () => undefined, 243 + ) 244 + const isValid = 245 + !!currentHandle && 246 + !!value?.handle && 247 + value.handle === currentHandle && 248 + currentHandle !== 'handle.invalid' 249 + return { 250 + $type: 'app.bsky.actor.defs#verificationView', 251 + issuer: ref.did, 252 + issuerHandle: issuer?.handle, 253 + uri, 254 + isValid, 255 + createdAt: value?.createdAt ?? new Date(0).toISOString(), 256 + } 257 + }, 258 + ), 259 + ) 260 + ).filter(Boolean) as AppBskyActorDefs.VerificationView[] 261 + 262 + if (verifications.length === 0) return undefined 263 + 264 + const verifiedStatus = verifications.some(v => v.isValid) ? 'valid' : 'none' 265 + return { 266 + $type: 'app.bsky.actor.defs#verificationState', 267 + verifications, 268 + verifiedStatus, 269 + // We are not a trusted verifier ourselves; report none. 270 + trustedVerifierStatus: 'none', 271 + } 272 + } 273 + 274 + /** 200 275 * Hydrate a `ProfileViewDetailed` for a DID or handle from microcosm. 201 276 * 202 277 * Counts: `followersCount` / `followsCount` / `postsCount` are pre-computed ··· 247 322 248 323 const profile = recordRes?.value as AppBskyActorProfile.Record | undefined 249 324 325 + const verification = await hydrateVerificationState(did, handle, signal).catch( 326 + () => undefined, 327 + ) 328 + 250 329 return { 251 330 $type: 'app.bsky.actor.defs#profileViewDetailed', 252 331 did, ··· 262 341 indexedAt: undefined, 263 342 createdAt: profile?.createdAt, 264 343 pinnedPost: profile?.pinnedPost, 344 + verification, 265 345 } 266 346 } 267 347