Daily Bluesky bot for AT Mot. Invites players and congratulates yesterday's solvers.
0

Configure Feed

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

refactor: type untrusted Constellation JSON as unknown and narrow

get() returned any, so every downstream field access (data.total,
data.records, data.cursor) was unchecked at the one boundary where
external, untrusted JSON enters the worker — neutralizing the strict
tsconfig for that path. Return unknown and narrow each field at the
call site; this also makes getBacklinks reject a non-string cursor
instead of passing it through.

+8 -5
+8 -5
src/constellation.ts
··· 13 13 /** Source path Constellation indexes for the result record's leaderboard link. */ 14 14 const RESULT_TARGET_PATH = 'puzzleTarget'; 15 15 16 - async function get(path: string, params: Record<string, string>): Promise<any | null> { 16 + async function get(path: string, params: Record<string, string>): Promise<unknown> { 17 17 const url = new URL(path, CONSTELLATION_BASE); 18 18 for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v); 19 19 try { ··· 27 27 28 28 /** Distinct DIDs linking to `target`. Null on failure. */ 29 29 async function countDistinctDids(target: string, collection: string, dottedPath: string): Promise<number | null> { 30 - const data = await get('/links/count/distinct-dids', { 30 + const data = (await get('/links/count/distinct-dids', { 31 31 target, 32 32 collection, 33 33 path: dottedPath.startsWith('.') ? dottedPath : `.${dottedPath}`, 34 - }); 34 + })) as { total?: unknown } | null; 35 35 return typeof data?.total === 'number' ? data.total : null; 36 36 } 37 37 ··· 47 47 limit: String(opts.limit), 48 48 }; 49 49 if (opts.cursor) params.cursor = opts.cursor; 50 - const data = await get('/xrpc/blue.microcosm.links.getBacklinks', params); 50 + const data = (await get('/xrpc/blue.microcosm.links.getBacklinks', params)) as 51 + | { records?: unknown; cursor?: unknown } 52 + | null; 51 53 if (!data || !Array.isArray(data.records)) return null; 52 - return { records: data.records as BacklinkRecord[], cursor: data.cursor ?? null }; 54 + const cursor = typeof data.cursor === 'string' ? data.cursor : null; 55 + return { records: data.records as BacklinkRecord[], cursor }; 53 56 } 54 57 55 58 /**