neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
Bring the README and landing tiles up to what the forge does
7a1d662 · Gabriel Morell · 2026-09-11 04:56
Message
{commit_body(@commit)}
Files changed
modified
README.md
+23
−2
@@ -26,10 +26,22 @@ external tools (Forgejo runner, Garage, zot) rather than reinvent them.
| 26 | 26 | - **Full GFM markdown** with cross-references (`#42`, `#x2a` hex, `owner/repo#42`), GitHub-style alerts, footnotes, task lists, fenced-code syntax highlighting — cached per-render |
| 27 | 27 | - **Language stats**: 0.3em GitHub-style bar on the repo page driven by a per-commit Oban job; click for `/stats/languages` (full table) and `/stats/committers` (commits + churn per author) |
| 28 | 28 | - Per-user editor theme (curated subset of Lumis themes — Dracula, Solarized, Monokai, Tokyo Night, Catppuccin, etc) — separate from the daisyUI page theme |
| 29 | +- **Discovery** | |
| 30 | + - **Dashboard at `/`** for signed-in visitors — PRs waiting on your review (asked of you first, maintainer inference as a fallback), your open PRs and issues, CI, pinned and recently-pushed repos, org invitations. Logged-out visitors get the landing page | |
| 31 | + - **Topic tags** — up to seven per repo, plus one derived automatically from its primary language and kept current by the stats worker. Browse at `/tags`, filter the repo listing by them | |
| 32 | + - **Syms** — stars, but with a configurable set of symbols; instance-wide rankings at `/syms` | |
| 33 | + - Repository and organization listings as cards with filter, sort and scope, paginated and deep-linkable (`/repositories/2`, `/orgs/page/2`) | |
| 29 | 34 | - **Collaboration** |
| 30 | 35 | - Issues + comments with Write/Preview tabs, label picker, query-string autofill |
| 31 | 36 | - **Quote-reply** button on every comment — appends `> `-prefixed source with attribution |
| 32 | − - Pull requests with mergeability probe, 3-way merge, cross-repo (fork) PRs, line-level diff inline | |
| 37 | + - **History subpage** on every issue and PR — pushes (with sha pair and commit count), renames, description edits, labels, state changes, reviews, comment edits and moderation, interleaved in one timeline. Body edits fold their before/after into a collapsed diff that renders from the recorded payload, so it survives the comment being deleted | |
| 38 | + - **Cross-reference backlinks** — writing `#42` leaves a linked entry in *that* item's history, so the relationship reads from both ends. Only genuinely new references record, and a `#42` inside backticks is text rather than a link | |
| 39 | + - Pull requests with mergeability probe, 3-way merge, cross-repo (fork) PRs, reopen, and a **dedicated code review screen** at `/pulls/:n/files` — the diff gets the whole viewport instead of sharing a column with the discussion | |
| 40 | + - **Review flow** on its own tab: assigned reviewers (requested by handle, or from chips suggesting who actually reviews in this repo), one standing verdict per reviewer rather than a pile of contradictory rows, and the full log behind a disclosure | |
| 41 | + - **Line comments** anchored to a file and line, pinned to the head they were written against | |
| 42 | + - **Suggested changes** — a ```` ```suggestion ```` block renders as the proposed replacement with an Apply button that commits it to the source branch. Refuses rather than guesses: `:stale` if the branch moved since, and the ref update is a compare-and-swap so a concurrent push loses the race instead of being overwritten | |
| 43 | + - **Per-repo merge rules**, all off by default except the last: block merging while changes are requested, require N approving reviews, and stop authors approving their own PR (on for new repos). Repo admins can override, and an override is recorded as such | |
| 44 | + - **Editable titles and descriptions** on issues and PRs, plus editable and soft-deletable comments — deletion is soft so the history can still render what was edited before it went | |
| 33 | 45 | - Forks + fork-sync (fast-forward CAS) + compare-any-two-refs view |
| 34 | 46 | - **Repository import** from a GitHub org/user, a GitLab group (subgroups included) or user, or any single git URL — `git clone --mirror` per repo on its own background job, with a live progress page and an on-demand "fetch from upstream" re-sync. Git data only; issues and PRs don't come across. Provider tokens are encrypted at rest, handed to `git` out-of-band (never in the clone URL), and wiped when the import finishes |
| 35 | 47 | - Branch protection, deploy keys, webhooks, wikis |
@@ -43,12 +55,18 @@ external tools (Forgejo runner, Garage, zot) rather than reinvent them.
| 43 | 55 | - **Registration modes**: `:open` / `:invite_only` (default) / `:closed`, configurable per-instance |
| 44 | 56 | - **Invites** — single-use tokens with create / list / revoke per user; UI at `/users/settings/invites` |
| 45 | 57 | - **Org visibility**: `public` / `internal` / `private`. Repos can't be more open than their org; tightening an org cascades to over-public repos in one transaction. Public orgs are accessible to anonymous viewers; private orgs require membership. |
| 46 | − - **Org members management** at `/orgs/:handle/settings/members` — add by handle or email, change roles, remove, with a last-admin guard so an org can never end up admin-less | |
| 58 | + - **Org membership by invitation** at `/orgs/:handle/settings/members` — an admin invites by handle or email and the invitee accepts from their dashboard; nobody is added to an org without agreeing. Withdraw a pending invite, change roles, remove members, with a last-admin guard so an org can never end up admin-less | |
| 59 | +- **Moderation for owners** | |
| 60 | + - Org and repo admins get their own queue at `/orgs/:handle/settings/moderation` and `/r/:owner/:name/settings/moderation` — reports about *their* content, which previously only an instance admin could see | |
| 61 | + - **Scoped bans** on local users: a repo admin can stop someone acting in their repo, an org admin across every repo the org owns. Neither reaches further; suspending an account instance-wide stays an instance admin's power | |
| 62 | + - Bans stop writing — opening issues and PRs, commenting, reviewing — and fold away what the person already wrote in that scope. Hiding happens at render time, so lifting a ban restores everything without rewriting a row | |
| 63 | + - Optional expiry, with no sweeper to run: a lapsed ban simply stops matching. The row survives as a record of who banned whom, when, why, and who lifted it | |
| 47 | 64 | - **Auth & MFA** |
| 48 | 65 | - Magic-link login + email/password |
| 49 | 66 | - **TOTP** (any RFC 6238 authenticator) with QR enrollment + 10 single-use recovery codes |
| 50 | 67 | - **WebAuthn / FIDO2** — hardware security keys (YubiKey, Titan), platform authenticators (Touch ID / Windows Hello), browser passkeys |
| 51 | 68 | - Recovery codes shared across factors; instance-level enforcement with N-day grace period |
| 69 | + - **Sudo mode** on every credential-management page — settings, SSH keys, API tokens, two-factor, invites all demand a recent re-authentication, so a stolen session cookie can't enrol its own authenticator or mint a token | |
| 52 | 70 | - **Federation (ForgeFed / ActivityPub)** |
| 53 | 71 | - HTTP Signatures on inbound + outbound deliveries; outbound dead-letter after 8 retries |
| 54 | 72 | - Push / ticket / merge / comment activities outbound; per-task hourly key refresh of stale remote actors |
@@ -152,6 +170,7 @@ These all live in `config/*.exs`. Key ones:
| 152 | 170 | | `:registration_mode` | `:open` / `:invite_only` / `:closed` | `:invite_only` | |
| 153 | 171 | | `GitGud.Federation` `federation_mode` | `:allowlist` or `:open` | `:allowlist` | |
| 154 | 172 | | `GitGud.Cache` | Nebulex cache sizing | 50k entries / 200MB | |
| 173 | +| `:syms` | Symbols repos can be marked with; `[]` disables the feature | `["⭐", "🚀", "💔", "⁉️", "❤️"]` | | |
| 155 | 174 | | `GitGud.Accounts.TwoFactor` `required` / `grace_period_days` | Instance-wide MFA enforcement + grace window | `false` / `14` | |
| 156 | 175 | | `GitGud.Workflows.Workers.CacheEviction` `max_age_days` / `per_repo_max_mb` | `actions/cache` pruning knobs | `90` / `500` / `dry_run: false` | |
| 157 | 176 | | `GitGudWeb.PackagesWebhookController` `shared_secret` | Bearer-token gate on the zot webhook (env: `ZOT_WEBHOOK_SECRET`) | `nil` (open in dev) | |
@@ -197,6 +216,8 @@ The federation admin LiveView at `/admin/federation` exposes:
| 197 | 216 | - instance + actor block CRUD |
| 198 | 217 | - allowlist CRUD with mode toggle |
| 199 | 218 | - open report queue with dismiss / action / forward-to-source actions |
| 219 | + (instance-wide; org and repo admins see the reports scoped to their | |
| 220 | + own content on their own moderation pages) | |
| 200 | 221 | |
| 201 | 222 | Federated PRs (inbound `Offer`) materialize as local PR rows with |
| 202 | 223 | `source_actor_id` pointing at the remote actor and no `author_id`. |
modified
lib/git_gud_web/components/landing_components.ex
+25
−0
@@ -67,6 +67,31 @@ defmodule GitGudWeb.LandingComponents do
| 67 | 67 | title="Moderation up front" |
| 68 | 68 | body="Per-repo interaction policy, quarantine queue, rate limits, peer-block suggestions, and a reversible 'replace with mod message' that keeps the original visible to admins + author." |
| 69 | 69 | /> |
| 70 | + <.feature | |
| 71 | + icon="hero-hand-raised" | |
| 72 | + title="Owners moderate their own ground" | |
| 73 | + body="Org and repo admins see the reports about their content — not just the instance admin — and can ban someone from one repo or from every repo an org owns. A ban stops them writing and folds away what they already wrote, at render time, so lifting it restores everything." | |
| 74 | + /> | |
| 75 | + <.feature | |
| 76 | + icon="hero-check-badge" | |
| 77 | + title="Reviews that hold a verdict" | |
| 78 | + body="Assign reviewers, or take a chip suggesting who actually reviews here. One standing verdict each, not a pile of contradictory rows. Optional rules: block merging while changes are requested, require N approvals, stop authors approving their own — admins can override, and the override is recorded." | |
| 79 | + /> | |
| 80 | + <.feature | |
| 81 | + icon="hero-code-bracket-square" | |
| 82 | + title="Suggest a change, apply it" | |
| 83 | + body="Comment on a line, or propose the replacement in a suggestion block that anyone with write access can commit. Refuses rather than guesses — if the branch moved since, it says so, and the ref update is a compare-and-swap so a concurrent push can't be clobbered." | |
| 84 | + /> | |
| 85 | + <.feature | |
| 86 | + icon="hero-clock" | |
| 87 | + title="History on everything" | |
| 88 | + body="Pushes, renames, labels, reviews, edits and moderation in one timeline per issue and PR. Body edits fold their before/after into a collapsed diff. Writing #42 leaves a backlink in that item's history, so a reference reads from both ends." | |
| 89 | + /> | |
| 90 | + <.feature | |
| 91 | + icon="hero-magnifying-glass" | |
| 92 | + title="Find things by what they are" | |
| 93 | + body="Seven topic tags per repo plus one derived from its primary language, browsable at /tags. Syms — stars, but with a set of symbols. Listings filter, sort and paginate with links you can send someone." | |
| 94 | + /> | |
| 70 | 95 | <.feature |
| 71 | 96 | icon="hero-finger-print" |
| 72 | 97 | title="MFA + WebAuthn" |
modified
test/git_gud_web/live/page_live/home_test.exs
+8
−0
@@ -48,6 +48,14 @@ defmodule GitGudWeb.PageLive.HomeTest do
| 48 | 48 | assert html =~ "Forgejo Actions CI" |
| 49 | 49 | assert html =~ "Federation that works" |
| 50 | 50 | assert html =~ "Invite-gated signups" |
| 51 | + | |
| 52 | + # The tiles added as the forge grew — a stale grid is worse than | |
| 53 | + # a short one. | |
| 54 | + assert html =~ "Reviews that hold a verdict" | |
| 55 | + assert html =~ "Suggest a change, apply it" | |
| 56 | + assert html =~ "History on everything" | |
| 57 | + assert html =~ "Owners moderate their own ground" | |
| 58 | + assert html =~ "Find things by what they are" | |
| 51 | 59 | end |
| 52 | 60 | |
| 53 | 61 | test "no dashboard leaks to anonymous visitors", %{conn: conn} do |
Parents: 6280797