Skip to content

Latest commit

 

History

History
103 lines (79 loc) · 4.42 KB

File metadata and controls

103 lines (79 loc) · 4.42 KB

Architecture — RepoGraph

Source: validated PRD RepoGraph Side Project.md v2.0 §4-8. This document is the maintainability contract for contributors.

Monorepo Layout

repograph/
├── apps/
│   ├── web/                 # Next.js 15 (App Router) — landing, overview, explorer UI
│   └── api/                 # NestJS — GitHub integration, ingestion, graph queries
├── packages/
│   ├── graph-model/         # Pure TS types: GraphNode, GraphEdge, RelationshipType, confidence
│   ├── github-client/       # Hybrid GitHub GraphQL+REST client, pagination, ETag, token pool
│   ├── relationship-engine/ # Normalizes GitHub data → resolves identity → extracts relationships → dedup
│   ├── db/                  # Prisma schema (Postgres), migrations
│   ├── config/              # Shared ESLint / TSConfig / Tailwind preset
│   └── ui/                  # Design system tokens + primitives (award-level, delegated to agy)
├── docker-compose.yml
├── package.json (workspaces)
└── turbo.json

Why This Stack

Layer Choice Reason When to reconsider
Frontend Next.js 15 + Tailwind + XYFlow SSR landing, App Router, design system; XYFlow for progressive graph
Backend NestJS + Prisma + Redis + BullMQ Job dedup, rate-limit governor, incremental sync; Prisma typed DB Collapse to Next route handlers if single-container team (PRD §4.2)
DB PostgreSQL + JSONB generic nodes/edges Sufficient for ≤1M edges, recursive CTE hops ~50ms; no migration for new types Neo4j/AGE if depth 4+ or PageRank
Cache/Queue Redis + BullMQ Mandatory for token rotation, dedup, backoff

Key Contracts (Customizability)

1. packages/graph-model is pure types — no runtime deps

// Adding a new node type: extend union, no DB migration for UI
export type GraphNodeType = "repository" | "issue" | "pull_request" | "user";
// Adding a new relationship: register in registry
export const RELATIONSHIP_REGISTRY = { authored: {...}, reviewed: {...} } as const;

2. packages/github-client is pluginable

  • Token provider: TokenPool interface — PAT, GitHub App, or process.env.GITHUB_TOKEN
  • Cache layer: ETagStore — Redis or in-memory
  • Swap without touching business logic.

3. packages/relationship-engine is rule-based

  • Add relation: create single file in rules/<relation>.ts implementing RelationshipRule
  • Identity resolution: canonical user:github:<id> (see identity.ts)

4. packages/ui is token-driven

  • Theming via CSS vars + tailwind preset; dark/light, reduced-motion
  • Primitives: Button, Card, Badge, Input — never style inline

API Contracts

Graph Query — Must Fix #3 (cap + require focus)

GET /repositories/:id/graph?focus=issue:123&depth=1&timeWindow=30d&nodeTypes=issue,pr,user&limit=300
→ { nodes[], edges[], meta: { focus, depth, complete, ingestionState, cacheHit, truncated } }

400 if !focus
400 if depth>2
400 if limit>400
Cache: graph:{owner}:{repo}:{focus}:{depth}:{timeWindow}:{hash(filters)} TTL 10m

Repository Resolve

POST /repositories/resolve  { url: "https://github.com/goharbor/harbor.git" }
→ { id, fullName, status, cached }

Ingestion Status

GET /repositories/:id/status → { state: discovered|indexing|partially_ready|ready|refreshing|partial_error, ingested, total, lastError }

Rate-Limit Governor (Must Fix #1,5)

  • Token rotation, leaky bucket 1 req/s/token, Retry-After honor
  • Secondary limit accounting: 900 REST pts/min, 2000 GraphQL pts/min, 100 concurrent
  • Redis SETNX ingestion:lock:{repoId} EX 300 + jobId = repo:fullName:etag

Relationship Tiers (Must Fix #2,4)

  • Tier 1 eager edges: authored, assigned, reviewed, review_requested, closes_via_keyword (confidence high/medium) → materialized in edges
  • Tier 2 lazy: mentioned, referenced → fetched timeline on-demand for focus neighbors only
  • Evidence: edge.evidence[] { source, url } rendered as one-sentence tooltip

Performance Guardrails

  • Frontend: viewport rendering, memoized nodes/edges, WebWorker layout, maxNodes 400
  • Backend: indexed queries, cached subgraphs, background jobs
  • DB: GIN(metadata), (repo_id,type), BRIN(timestamps)

Contribution Boundaries

  • core/ (this repo): Apache-2.0 forever
  • enterprise/ (private, teams, AI, history): separate license

See CONTRIBUTING.md for workflow.