Skip to content

staging → main: update-posting fix, performance pass, security hardening - #241

Merged
holkexyz merged 45 commits into
mainfrom
staging
Aug 12, 2026
Merged

staging → main: update-posting fix, performance pass, security hardening#241
holkexyz merged 45 commits into
mainfrom
staging

Conversation

@holkexyz

Copy link
Copy Markdown
Member

Rolls up 45 commits on staging. The bulk is a performance and code-quality pass (#237), with security hardening, an auth/CI change, and one user-facing bug fix.

Bug fix

  • Posting an activity update 403'd with "collection is required and must be an allowed collection". An update is stored as an org.hypercerts.context.attachment record, and that NSID was never in the XRPC proxy's ALLOWED_WRITE_COLLECTIONS — so create, edit, and delete of own-repo updates were all broken. Group-owned updates were unaffected (different route, which allowlisted the NSID itself). Broken since the allowlist was introduced, not a recent regression.
  • Same form: document attachments now work. allowAnyType only skipped the client-side check, so PDFs 415'd at both upload routes. Documents are now an opt-in set selected by ?purpose=attachment, additive over each route's existing image list — a PDF still cannot land as an avatar. text/html and image/svg+xml stay excluded from both, since blobs are served under the PDS origin.

Performance (#237)

Lazy-loaded profile tabs, settings, the TipTap editor, and the contributor board. Memoized feed, explore, and endorsement rows. Single-flight caches for endorsement and follow hooks; batched project fetches through the indexer with PDS fallback; collapsed the hyperboard waterfall; parallel Upstash round-trips in the xrpc proxy; graph redraw paused when idle. Server-rendered landing stats and router staleTimes.

Security

SSRF filter and PDS proxy redirect/limit hardening, per-target unlock throttle, feedback email relay removed, org-limit fail-open closed, CGS timeouts. New test coverage for password-reset, clone-blob SSRF, members escalation, and upload-blob limits.

Refactors and cleanup

Shared helpers (deriveIdentity, rkeyFromUri, formatTimePeriod, projectImage) replacing 50+ duplicated call sites; postIndexer unified across indexer calls with a domain-split lib; dead hooks, exports, and orphaned tests removed; the react-hooks lint warning backlog resolved across 36 files; type validation added at record, storage, and auth-error boundaries.

CSS and tokens

Z-index, shadows, and status colors tokenized; raw rgba replaced with theme-aware tokens; invariant scrim tokens added.

Auth and CI

Vercel preview origin support with shared loopback host validation; production build now runs in PRs with an ephemeral cookie secret.

Verification

npx tsc --noEmit clean, npm run lint silent, 1235/1235 tests passing locally.

Known follow-ups (not in this PR)

  • The XRPC proxy synthesizes { error: "Upstream PDS returned 400" } for public getRecord, destroying the RecordNotFound discriminator that use-org-marker.ts checks for. The negative-cache write never fires, so every profile mount re-issues the request.
  • Staging still points at the prod indexer pending magic-indexer#273.

🤖 Generated with Claude Code

holkexyz and others added 30 commits July 2, 2026 23:41
10-dimension review with adversarial verification: 62 findings, 36 confirmed. Records the executable prompt, per-finding evidence/verdicts, and the disjoint-ownership implementation plan (34 fixes across 11 tracks, 2 deferred).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Validate .well-known handles as hostnames and gate them through isAllowedPdsUrl before fetch (closes unauthenticated SSRF where an IP/host:port handle reached the server fetch).
- Reject non-canonical IPv4 literals (decimal/hex/octal/short-form) via a glibc inet_aton-matching parser; add 0.0.0.0/8 and 100.64.0.0/10 (CGNAT) to the blocklist.
- Set redirect:"error" on all upstream PDS/appview fetches (xrpc proxy get/list/getBlob, getCertsProfile, getRecordServer, DID-doc, createSession) so an allowed host cannot 30x the server onto an internal target.
- Add an IP-scoped rate limiter to the unauthenticated xrpc GET proxy.
- Cap the foreign getBlob stream by counting bytes, independent of the declared Content-Length.
- Pure-JS IP validation (no node:net) since @/lib/atproto/did is imported by client modules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… relay

- Group-account unlock now consults a per-target (groupDid) limiter alongside the per-caller one and denies if either trips, so an attacker with many caller DIDs can no longer multiply password guesses against one victim account. Fail-closed behavior preserved.
- Feedback route no longer emails attacker-controlled content to an attacker-supplied recipient; only the internal team notification remains, with the submitter address used solely as Reply-To.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…adata, tighten robots

- Scope X-Frame-Options: DENY / CSP frame-ancestors 'none' to non-embed routes and allow framing on /embed/* so the shipped third-party board embed works again.
- Convert root / to a Server Component that reads the session cookie and redirects (307) to /home or /welcome, removing the client-bundle load + spinner flash.
- Wrap OG generateMetadata upstream fetches in unstable_cache (revalidate 300s) to cut repeated crawler/share-scraper TTFB.
- Disallow /workspace, /endorsement-graph, /profile in robots.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…activity rows

- Wrap the TipTap-based LeafletEditor (~9.7 MB dep tree) in next/dynamic({ssr:false}) and route all 8 import sites through the wrapper, removing it from read-heavy first-load bundles (profile, activity-detail, project-detail); it loads only on entering edit mode.
- Lazy-load the d3-hierarchy contributor board (ActivityFancyBoard) so it loads only when the Contributors tab opens.
- Memoize weight-percent maps and contributor rows in activity-detail so read-only rows don't re-render on edit keystrokes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…arks; dedupe truncateDid

- useMemo the explore sorted lists and wrap the result rows (cert/account/project/user/project-card/funding) in React.memo so unchanged rows bail on each search keystroke.
- Memoize profile endorsement cards and drop the duplicate in-grid filter/sort.
- Change the nested inner page-level <main> in explore (x2) and home to <div> (class-only CSS selectors, so the >=1300px baseline is unchanged) - fixes duplicate main landmarks (WCAG 1.3.1).
- Replace the two triplicated local truncateDid copies in explore-page with the shared helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Split the monolithic NavbarContext into a memoized setters context and a values context, so setter-only consumers (usePageTitle callers across pages) stop re-rendering when navbar values change. Public hook API is unchanged.
- Render the page-title chrome as an <h1> so primary pages have a programmatic heading (WCAG 1.3.1 / 2.4.6); mobile and desktop bars are mutually display:none so only one h1 is ever in the a11y tree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…session on HTTP error

- Home-feed loadMore now runs under an AbortController/generation guard so a filter toggle mid-pagination no longer appends stale, filter-violating events.
- useUserIndexerActivities de-dupes by URI when merging pages, eliminating duplicate rows and duplicate React keys.
- useSession no longer permanently caches a null handle/email on a non-OK getSession response; it resets so the next mount refetches.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…esize storm

- useProjectItems resolves item URIs through the indexer's batch-by-URI query (chunks of 50), falling back to per-URI getRecord only for URIs the indexer reports missing - turning an N-request fan-out on project-detail into ~1.
- useLayoutBreakpoints guards its setter with an equality check so unchanged breakpoints during a resize drag no longer re-render every consumer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t scrim tokens

- Swap hardcoded rgba hover/tint/shadow literals for the existing theme-aware tokens (--overlay-weak/-medium, --color-success-bg/-error-bg/-error-border, --shadow-md, --navbar-bg) so hover feedback and status tints flip correctly in dark mode.
- Add invariant --scrim-pill/-hover/-ghost tokens and reference them from the 8 duplicated image-overlay pill scrim sites.
- Delete the hand-written leaflet-attribution dark override now that the token flips.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Delete the never-imported activity-contributor-board component and four unused exports (GuillocheMeshQuiet, fetchContributorInformation, scopeKey, clearTourCompleted), each verified to have zero references.
- Replace the workspace-pane local truncateDid copy with the shared helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tion, upload-blob limits

Add regression tests for previously-untested security-adjacent routes: group password-reset cross-account verify (409 on identity mismatch), onboarding clone-blob host-allowlist + redirect:error SSRF guards, members anti-escalation (cannot add a member directly as owner), and upload-blob content-type allowlist + size cap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…indings, track plan

73 confirmed findings across 9 review dimensions plus an exhaustive triage
of all 63 lint warnings; every finding adversarially verified (2 skeptics
for high severity). Implementation plan: 11 parallel disjoint-ownership
tracks + 2 sequential cross-cutting tracks, nothing deferred.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hase 0/1.5

Two plan reviewers (ownership/coupling, sequencing/risk). Accepted: app-dialog
to CSS track, finding 9/15 dedup, ma-earth split across T7 + phase 1.5 with
PDS fallback, phase-0 shared helpers, lint gate restated (<=2 warnings, 0
unused-disable), 5 new tests, T7/T9 commit splits, 7 file-list corrections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
postIndexer: single rich-result wrapper ({ok,status,data,errors}) for the
hand-rolled POST /api/indexer blocks; never throws on HTTP errors so each
call site keeps its exact throw/fail-soft/warn semantics when migrated.
deriveIdentity: canonical displayName/handle/initials/href/avatar
derivation with record-level overrides, replacing ~20 drifting copies.
Phase 0 of docs/perf-quality-2026-07-12/plan.md; call-site migration
follows in later tracks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
HomeFeedRow/EndorsementGroupRow/HomeFeedBody memoized (element-wise group
comparator per review); grouped-endorsement expansion windows 50 accounts
per click instead of mounting up to ~1000; row/sentence/preview layer moved
verbatim to home-feed-rows.tsx (CertPreview re-exported for tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…chunks

Re-enable autoPauseRedraw with a repaintEpoch bumped on image preload and
theme flips (paintNode/linkColor deps); force config no longer re-applies
and reheats on container resize; NetworkActorsByDids chunks fetch via
Promise.all; AllEndorsements loader switched to the cacheable indexer GET
contract (op/badgeType/first/after).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, router staleTimes; metadata fixes

Profile route loads SettingsPanel/ProfileEndorsements/ProfileFollowers/
ProfileLists via next/dynamic (OrgSettings likewise inside settings-panel);
landing network stats server-fetched in the ISR render via
network-counts-server.ts (fail-soft, 5s timeout) with the client hook as
null-field fallback; experimental.staleTimes.dynamic=30; double-Certified
title suffixes fixed (workspace/explore/endorsement-graph); dead /about
sitemap entry removed; /apps converted to a server component with an
SsoAppLink island; /home and /project/new gain titles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…r bodies at boundaries

coerceClaimActivityValue normalizes malformed PDS records before render in
use-activity and use-project-items; sessionStorage active-org restore is
shape-validated; /api/auth/login non-JSON error bodies no longer surface
raw SyntaxError to the sign-in form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… CGS resolution, collapse hyperboard waterfall

createCachedDidResource factory (module cache + stale window + abort-safe
fetch + refetch) adopted by use-followers/use-following; in-flight
coalescers added to use-received-endorsements, use-endorsements,
fetchDisplayProfile/fetchBoardForActivity; use-endorsement-lists moves from
permanent force-refetch to a versioned cache bus; use-cgs-memberships
resolves groups through the batched DID resolver; useHyperboard fetches
displayProfiles per-identity instead of behind a global barrier; rewritten
fetchers ride postIndexer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ing components; drop dead draft plumbing

useContextUpdates gains a 30s shared cache + in-flight dedupe (invalidated
from UpdateForm saves), halving duplicate fetches on activity/project
detail; useRouteRkey derives during render instead of a post-mount effect
(kills a guaranteed second render of the 2300-line component); trailing
component cluster moved to cert-detail-parts.tsx; contributorKey/
contributionRoleText deduped into lib/atproto/contributor-display.ts;
never-read swap-draft writes removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…stable callbacks; split below-fold + modals

EndorsementSubjectRow (on deriveIdentity, info+isLoading props) replaces
three drifted row copies; ProfileEndorsements calls useGivenEndorsements
once and derives the endorsed-set from it; row onToggle handlers are
useCallback-stable so list memos hold; below-fold views split to
profile-endorsement-views.tsx and the three list modals to their own
module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…loaders/filters/results

ExploreSearchField owns keystroke state + 350ms debounce (was re-rendering
the full results tree per keypress, twice over via the copy-pasted block in
the All view); All-view blocks fetch 2x block size instead of 4x50 for 5
rendered items (funding keeps the full window for the client-side
Confirmed-by filter); use-explore.ts loader layer split to
use-explore-loaders.ts; quality filters and results area extracted;
explore.tsx 2131 -> ~1480 lines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…modules

OPERATIONS/validation moved to operations.ts + variables.ts (pure module
split); new GET handler for an explicit CACHEABLE_OPS allowlist (five
zero-variable counts s-maxage=300 swr=86400; AllEndorsements pages
s-maxage=60 swr=600; no cache headers on upstream errors); CollectionsByUris
batch op added for the Ma Earth loader; allowlist + cache-header tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ound-trips in xrpc proxy

Foreign-repo/blob GETs no longer restore the caller's OAuth session
(hottest read path did a full token restore per request); immutable
CID-addressed blobs get s-maxage (foreign) and private max-age (own-repo);
rate-limit INCR and session lookup run concurrently; lazy-restore
regression tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…he headers

Group-registration limit check now fails closed on CGS errors and stops
walking member lists once the limit is provably unreachable; direct CGS
fetches carry abort timeouts; public group profile/metadata GETs get short
private cache headers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54x set-state-in-effect + 2x exhaustive-deps + 6x no-img-element triaged
per docs/perf-quality-2026-07-12/findings.md: fetch-reset effects now
compare previous keys inline, prop-mirrors derive during render, event
work moved to handlers, mounted/matchMedia flags ride
useSyncExternalStore; 20 sites where the pattern is deliberately correct
carry justified eslint-disable comments. Repo lint output: 63 warnings ->
0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
use-display-profile / use-pending-awards-count / use-user-activities (zero
production importers) removed with their test files; dead exports dropped
from account-email, app-passwords, urls, activity-uri; parseLocationCoords
de-exported; stale doc references fixed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…iewport shrink

Onboarding modal remounts per open via key so draft seeding is
initialization instead of a set-state-in-effect (also stops the bsky-graph
sync mounting on every page while closed); tour context exposes a clamped
stepIndex and clamps back() so a mid-tour resize across 800px cannot
strand the step index past the shorter steps array; covered by new
tour-context tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…contain long lists

All literal z-index rules mapped onto the --z-* scale (stacking table in
findings.md; new --z-local-raise + --z-skip-nav tokens); error focus ring
and status colors tokenized (dark mode now legible); --shadow-modal token
replaces three literal copies; 2px radius literals -> var(--radius); ~640
lines of orphaned CSS removed (live compound-selector partners preserved);
content-visibility + contain-intrinsic-size on home-feed and explore
lists; app-dialog latest-ref writes moved into an effect (react-hooks/refs
errors surfaced when the stale disable directive was removed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
holkexyz and others added 15 commits July 13, 2026 05:50
…back

fetchIndexerProjectsByUris batches the curated-URI set through the new
CollectionsByUris proxy op (50-URI chunks, postIndexer, ok flag instead of
throws); the Ma Earth loader tries the batch, restores curator order, and
falls back to the untouched per-URI PDS path on error or empty-but-expected
results — shippable whether or not the deployed magic-indexer supports the
uri-in filter yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…b, surface HTTP errors

19 remaining hand-rolled POST /api/indexer blocks migrated onto postIndexer
with per-site semantics preserved; fetchCount rides the cacheable GET
variant (dev mock-fetch-provider taught the GET form); indexer.ts split
into indexer-{funding,closure,counts,collections}.ts behind a re-export
barrel (1558 -> 597 lines, 30+ importers unchanged);
fetchIndexerActivities/ByUris now throw on HTTP !ok instead of rendering
an empty feed, keeping warn+fail-soft only for 200-with-GraphQL-errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Image helpers replace 50+ duplicated sites

16 more identity-fallback sites ride deriveIdentity (record-level
overrides via the options bag; unresolved DIDs now uniformly truncated
instead of raw 40-char strings or 'Anonymous'); rkeyFromUri joins
parseAtUri in lib/urls (4 private extractRkey, 2 private parseAtUri, 16
inline split-pop sites removed); formatTimePeriod shared across the four
date-range copies; slot-aware projectTitle/projectImage in collection.ts
fix the confirmed home-rail thumbnail precedence drift while keeping
banner-first hero slots; 14 new unit tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…taleness; round-2 cleanups

Object.hasOwn guards on the indexer op lookups (prototype keys die at the
first gate, pinned by tests); shared indexer plumbing moved to a leaf
indexer-client.ts so the domain split is acyclic; ExploreSearchField
debounce reads latest onCommit/search via effect-synced refs (could
previously revert a URL change made mid-window); repaintEpoch bumps
coalesced to one per frame; explore content-visibility scoped to the list
variants where containment can apply; CertPreview compat re-export dropped;
stale operations.ts comment pointers, suppression justifications, and
zero-consumer exports cleaned up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cross-repo follow-ups

Live probing of the prod indexer showed the three recorded magic-indexer
follow-ups need no upstream work: uri-in filtering already works (real-URI
probe returns the node), avatar is already in the lexicon-built schema (the
nulls mirror the PDS records, verified for 30), and authorLabels validates
on the same connection. The genuine gap was app-side: Projects/UserProjects/
ProjectsContainingCert never selected avatar — now they do, so projectImage's
avatar-first thumb precedence reaches indexer-fed surfaces. Evidence in
docs/perf-quality-2026-07-12/followups-probe.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Performance & code-quality pass 2026-07-12: 84 verified findings, lint 63 to 0, nothing deferred
…-indexer#273

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Prefer PUBLIC_URL for OAuth callbacks, then VERCEL_BRANCH_URL and VERCEL_URL. Allow same-origin CSRF requests on each exact configured deployment origin without making those origins cross-origin peers.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Add the existing npm build command to the pull-request verification job after tests.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
Co-Authored-By: OpenAI Codex <noreply@openai.com>
ci: run production build in pull requests
Posting an activity update 403'd with "collection is required and must be
an allowed collection". An update is stored as an
org.hypercerts.context.attachment record (contentType: "update" — there
is no separate update lexicon), and that NSID was never added to
ALLOWED_WRITE_COLLECTIONS. The gate covers all three REPO_METHODS, so
create, edit, and delete of own-repo updates were all broken. Group-owned
updates worked, because they route through /api/groups/[groupDid]/update,
which allowlists the NSID itself.

Not a recent regression: the allowlist has held the same entries since
3b37f3e introduced it, and this NSID never appeared in it. AGENTS.md
carries it as known pitfall #5.

Also fixes the blocker directly behind it. UpdateForm asked for
allowAnyType so it could attach PDFs, but that flag only skipped the
client-side check — both upload routes independently enforce an
image-only MIME allowlist and 415'd. Adds an opt-in document set,
selected by ?purpose=attachment, additive over each route's existing
image list so a PDF still cannot land as an avatar or banner. text/html
and image/svg+xml stay out of both: blobs are served back under the PDS
origin, so either is a stored-XSS vector there.

Each route keeps its own image allowlist and size cap unchanged. The
client attachment cap drops from 25MB to 4MB — Vercel rejects serverless
bodies over ~4.5MB, so the old ceiling only ever bought a failed
round-trip — and the file picker gains a matching accept attribute.

Tests: allowed-collections pins every written collection against the gate
plus the app.bsky.actor.profile invariant; upload-blob-types and the
group route cover the purpose switch and the html/svg exclusions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
certified-app Ready Ready Preview Aug 12, 2026 2:22pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 262 files, which is 162 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d6c4a736-7863-4254-94cb-546ec733c008

📥 Commits

Reviewing files that changed from the base of the PR and between 6788152 and 6c9b282.

📒 Files selected for processing (262)
  • .env.local.example
  • .github/workflows/ci.yml
  • AGENTS.md
  • README.md
  • docs/full-review-2026-07/findings.md
  • docs/full-review-2026-07/plan.md
  • docs/full-review-2026-07/prompt.md
  • docs/perf-quality-2026-07-12/findings.md
  • docs/perf-quality-2026-07-12/followups-probe.md
  • docs/perf-quality-2026-07-12/plan.md
  • docs/perf-quality-2026-07-12/prompt.md
  • docs/perf-quality-2026-07-12/review-round-1.md
  • docs/perf-quality-2026-07-12/review-round-2.md
  • next.config.ts
  • src/app/[actor]/[type]/[rkey]/update/[updateRkey]/edit/page.tsx
  • src/app/[actor]/[type]/[rkey]/update/new/page.tsx
  • src/app/[actor]/page.tsx
  • src/app/__tests__/robots-app-only-disallow.test.ts
  • src/app/api/feedback/__tests__/route.test.ts
  • src/app/api/feedback/route.ts
  • src/app/api/groups/[groupDid]/account/session/__tests__/route.test.ts
  • src/app/api/groups/[groupDid]/account/session/route.ts
  • src/app/api/groups/[groupDid]/members/__tests__/route.test.ts
  • src/app/api/groups/[groupDid]/metadata/route.ts
  • src/app/api/groups/[groupDid]/password-reset/__tests__/route.test.ts
  • src/app/api/groups/[groupDid]/profile/route.ts
  • src/app/api/groups/[groupDid]/upload-blob/__tests__/route.test.ts
  • src/app/api/groups/[groupDid]/upload-blob/route.ts
  • src/app/api/groups/memberships/route.ts
  • src/app/api/groups/register/__tests__/org-limit-fail-closed.test.ts
  • src/app/api/groups/register/__tests__/org-limit-member-walk.test.ts
  • src/app/api/groups/register/route.ts
  • src/app/api/indexer/__tests__/get-cacheable.test.ts
  • src/app/api/indexer/__tests__/route.test.ts
  • src/app/api/indexer/operations.ts
  • src/app/api/indexer/route.ts
  • src/app/api/indexer/variables.ts
  • src/app/api/onboarding/clone-blob/__tests__/route.test.ts
  • src/app/api/resolve-did/resolve-core.ts
  • src/app/api/xrpc/[...method]/__tests__/allowed-collections.test.ts
  • src/app/api/xrpc/[...method]/__tests__/get-blob-foreign.test.ts
  • src/app/api/xrpc/[...method]/__tests__/lazy-restore.test.ts
  • src/app/api/xrpc/[...method]/__tests__/same-session-fallback.test.ts
  • src/app/api/xrpc/[...method]/__tests__/upload-blob-types.test.ts
  • src/app/api/xrpc/[...method]/__tests__/xrpc-error.test.ts
  • src/app/api/xrpc/[...method]/route.ts
  • src/app/apps/page.tsx
  • src/app/apps/sso-app-link.tsx
  • src/app/create/page.tsx
  • src/app/endorsement-graph/page.tsx
  • src/app/endorsements/page.tsx
  • src/app/explore/page.tsx
  • src/app/home/page.tsx
  • src/app/page.tsx
  • src/app/project/new/layout.tsx
  • src/app/project/new/page.tsx
  • src/app/robots.ts
  • src/app/settings/edit-profile/page.tsx
  • src/app/sitemap.ts
  • src/app/styles/cert-detail.css
  • src/app/styles/components.css
  • src/app/styles/explore.css
  • src/app/styles/feed.css
  • src/app/styles/home.css
  • src/app/styles/landing.css
  • src/app/styles/layout.css
  • src/app/styles/pages.css
  • src/app/styles/profile-edit.css
  • src/app/styles/profile-endorsements.css
  • src/app/styles/profile-groups.css
  • src/app/styles/profile-inline-edit.css
  • src/app/styles/profile-lists.css
  • src/app/styles/profile.css
  • src/app/styles/project-detail.css
  • src/app/styles/settings-page.css
  • src/app/styles/tokens.css
  • src/app/styles/workspace.css
  • src/app/workspace/page.tsx
  • src/components/badges/response-buttons.tsx
  • src/components/badges/response-menu.tsx
  • src/components/context/update-form.tsx
  • src/components/contributor-board/activity-contributor-board.tsx
  • src/components/contributor-board/share-embed-dialog.tsx
  • src/components/create/contributor-identity-card.tsx
  • src/components/create/location-picker-dialog.tsx
  • src/components/dashboard/custom-domain-modal.tsx
  • src/components/dev/mock-fetch-provider.tsx
  • src/components/endorsements/__tests__/endorsement-subject-row.test.tsx
  • src/components/endorsements/endorsement-row.tsx
  • src/components/endorsements/endorsement-subject-row.tsx
  • src/components/endorsements/new-endorsement-panel.tsx
  • src/components/explore-page/__tests__/explore-search-field.test.tsx
  • src/components/explore-page/account-list-row.tsx
  • src/components/explore-page/cert-list-row.tsx
  • src/components/explore-page/explore-project-card.tsx
  • src/components/explore-page/explore-results.tsx
  • src/components/explore-page/explore-search-field.tsx
  • src/components/explore-page/explore-types.ts
  • src/components/explore-page/explore-user-card.tsx
  • src/components/explore-page/explore.tsx
  • src/components/explore-page/funding-receipt-row.tsx
  • src/components/explore-page/project-list-row.tsx
  • src/components/explore-page/quality-filters.tsx
  • src/components/feed/activity-author.tsx
  • src/components/feed/activity-detail.tsx
  • src/components/feed/activity-edit-route.tsx
  • src/components/feed/cert-detail-parts.tsx
  • src/components/home/__tests__/cert-preview-location-icon.test.tsx
  • src/components/home/__tests__/endorsement-group-row.test.tsx
  • src/components/home/home-feed-rows.tsx
  • src/components/home/home-feed.tsx
  • src/components/home/home.tsx
  • src/components/landing/guilloche-art.tsx
  • src/components/landing/landing-page.tsx
  • src/components/landing/sections/network-stats.tsx
  • src/components/layout/desktop-top-bar.tsx
  • src/components/layout/mobile-sidebar.tsx
  • src/components/layout/navbar.tsx
  • src/components/leaflet/leaflet-editor-dynamic.tsx
  • src/components/lists/add-to-list-menu.tsx
  • src/components/onboarding/onboarding-modal.tsx
  • src/components/onboarding/steps/step-graph.tsx
  • src/components/onboarding/steps/step-profile.tsx
  • src/components/profile/endorsement-lists.tsx
  • src/components/profile/list-modals.tsx
  • src/components/profile/person-card.tsx
  • src/components/profile/profile-endorsement-views.tsx
  • src/components/profile/profile-endorsements.tsx
  • src/components/profile/profile-follow-endorse.tsx
  • src/components/profile/profile-followers.tsx
  • src/components/profile/profile-header.tsx
  • src/components/profile/profile-lists.tsx
  • src/components/profile/profile-overview.tsx
  • src/components/profile/profile-projects.tsx
  • src/components/project/project-detail.tsx
  • src/components/project/project-edit-route.tsx
  • src/components/right-rail/news-section.tsx
  • src/components/settings/settings-panel.tsx
  • src/components/settings/sync-social-graph-section.tsx
  • src/components/ui/app-dialog.tsx
  • src/components/ui/bottom-sheet.tsx
  • src/components/ui/checkbox.tsx
  • src/components/ui/theme-toggle.tsx
  • src/components/ui/tooltip.tsx
  • src/components/visualization/endorsement-graph.tsx
  • src/components/workspace/workspace-pane.tsx
  • src/components/workspace/workspace-types.ts
  • src/components/workspace/workspace.tsx
  • src/hooks/__tests__/create-cached-did-resource.test.tsx
  • src/hooks/__tests__/use-activity-malformed-value.test.tsx
  • src/hooks/__tests__/use-context-updates.test.tsx
  • src/hooks/__tests__/use-endorsement-graph.test.tsx
  • src/hooks/__tests__/use-explore-loaders.test.ts
  • src/hooks/__tests__/use-followers-singleflight.test.tsx
  • src/hooks/__tests__/use-given-endorsements-singleflight.test.tsx
  • src/hooks/__tests__/use-home-feed-loadmore-abort.test.tsx
  • src/hooks/__tests__/use-layout-breakpoints.test.tsx
  • src/hooks/__tests__/use-pending-awards-count-logged-out.test.tsx
  • src/hooks/__tests__/use-project-items.test.tsx
  • src/hooks/__tests__/use-received-endorsements-singleflight.test.tsx
  • src/hooks/__tests__/use-session-retry.test.tsx
  • src/hooks/__tests__/use-user-activities.test.tsx
  • src/hooks/__tests__/use-user-indexer-activities-dedupe.test.tsx
  • src/hooks/create-cached-did-resource.ts
  • src/hooks/use-activity-funding.ts
  • src/hooks/use-activity.ts
  • src/hooks/use-author-info.ts
  • src/hooks/use-bottom-sheet-drag.ts
  • src/hooks/use-cert-projects.ts
  • src/hooks/use-cgs-memberships.ts
  • src/hooks/use-context-updates.ts
  • src/hooks/use-contributor-info.ts
  • src/hooks/use-contributor-information-record.ts
  • src/hooks/use-display-profile.ts
  • src/hooks/use-endorsement-graph.ts
  • src/hooks/use-endorsement-lists.ts
  • src/hooks/use-endorsements.ts
  • src/hooks/use-evaluator-endorsements.ts
  • src/hooks/use-explore-loaders.ts
  • src/hooks/use-explore.ts
  • src/hooks/use-followers.ts
  • src/hooks/use-following.ts
  • src/hooks/use-home-feed.ts
  • src/hooks/use-hyperboard.ts
  • src/hooks/use-layout-breakpoints.ts
  • src/hooks/use-location.ts
  • src/hooks/use-managed-projects.ts
  • src/hooks/use-mounted.ts
  • src/hooks/use-network-counts.ts
  • src/hooks/use-org-marker.ts
  • src/hooks/use-own-certs.ts
  • src/hooks/use-pending-awards-count.ts
  • src/hooks/use-profile-pds.ts
  • src/hooks/use-project-items.ts
  • src/hooks/use-received-endorsements.ts
  • src/hooks/use-rights.ts
  • src/hooks/use-session.ts
  • src/hooks/use-user-activities.ts
  • src/hooks/use-user-indexer-activities.ts
  • src/hooks/use-workspace.ts
  • src/lib/__tests__/urls.test.ts
  • src/lib/atproto/__tests__/activity-uri.test.ts
  • src/lib/atproto/__tests__/coerce-claim-activity.test.ts
  • src/lib/atproto/__tests__/collection.test.ts
  • src/lib/atproto/__tests__/collections-by-uris.test.ts
  • src/lib/atproto/__tests__/contributor-display.test.ts
  • src/lib/atproto/__tests__/did-ssrf.test.ts
  • src/lib/atproto/__tests__/indexer-activities.test.ts
  • src/lib/atproto/__tests__/indexer-counts.test.ts
  • src/lib/atproto/__tests__/network-counts-server.test.ts
  • src/lib/atproto/__tests__/post-indexer.test.ts
  • src/lib/atproto/account-email.ts
  • src/lib/atproto/activity-uri.ts
  • src/lib/atproto/app-passwords.ts
  • src/lib/atproto/badges.ts
  • src/lib/atproto/blob-types.ts
  • src/lib/atproto/coerce-claim-activity.ts
  • src/lib/atproto/collection.ts
  • src/lib/atproto/contributor-display.ts
  • src/lib/atproto/did.ts
  • src/lib/atproto/follow.ts
  • src/lib/atproto/follower-events.ts
  • src/lib/atproto/get-record-server.ts
  • src/lib/atproto/hyperboard.ts
  • src/lib/atproto/indexer-client.ts
  • src/lib/atproto/indexer-closure.ts
  • src/lib/atproto/indexer-collections.ts
  • src/lib/atproto/indexer-counts.ts
  • src/lib/atproto/indexer-funding.ts
  • src/lib/atproto/indexer.ts
  • src/lib/atproto/location.ts
  • src/lib/atproto/network-counts-server.ts
  • src/lib/atproto/profile.ts
  • src/lib/atproto/trusted-evaluators.ts
  • src/lib/atproto/typed-lists.ts
  • src/lib/atproto/workspace.ts
  • src/lib/auth/__tests__/csrf.test.ts
  • src/lib/auth/__tests__/login-response-guards.test.tsx
  • src/lib/auth/__tests__/oauth-config.test.ts
  • src/lib/auth/auth-context.tsx
  • src/lib/auth/csrf.ts
  • src/lib/auth/group-account-session.ts
  • src/lib/auth/oauth-client.ts
  • src/lib/groups/__tests__/org-context-persisted.test.tsx
  • src/lib/groups/org-context.tsx
  • src/lib/groups/use-org-limit.ts
  • src/lib/navbar-context.tsx
  • src/lib/og-metadata.ts
  • src/lib/onboarding/onboarding-context.tsx
  • src/lib/tour/__tests__/tour-context.test.tsx
  • src/lib/tour/tour-context.tsx
  • src/lib/tour/tour-sentinel.ts
  • src/lib/urls.ts
  • src/lib/utils/__tests__/config.test.ts
  • src/lib/utils/__tests__/format-date.test.ts
  • src/lib/utils/__tests__/identity.test.ts
  • src/lib/utils/__tests__/swap-drafts.test.ts
  • src/lib/utils/config.ts
  • src/lib/utils/format-date.ts
  • src/lib/utils/identity.ts
  • src/lib/utils/swap-drafts.ts
  • tailwind.config.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@holkexyz
holkexyz marked this pull request as ready for review August 12, 2026 14:27
@holkexyz
holkexyz merged commit 1db0d8f into main Aug 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants