🐸 Frogue(Fed)

~ololduck/Frogue

Raw

Stuff to implement

  • be jj-aware for single-commit patch proposals
  • be jj-aware for stacked changes

ssh git access

  • fetch from repository
    • Allow unenthicated ssh git fetches?
      • Refuse the connection if a connection uses a non-git user and doesn't present a key matching the username they use. Explain that they should use the git user if they don't have an account.
  • push to repository
  • Add an error message and close the connection if the user did not set an SSH key.
  • Add flood protection/mitigation

SSH ui -- nice to have, not a priority

if a user directly logs in with something like ssh username@SSH_SERVER_ADDRESS, show a TUI version of the Web UI. Maybe that could even be the main registration funnel?

  • be able to do common operations via ssh TUI. could be cool to be able to be out of the browser to contribute on the forge.

Web

  • create a logo (maybe (probably) a cute child-like smiling frog) meh emoji will do
  • global style integrated into the templates via <link type="text/css" … />
  • maximize screen real-estate: no huge header, attempt to group logical information in the same block, attempt to put blocks side-by-side.
  • Have a 404 page.
  • Add todo support (- [ ]/- [x]) to rendered markdown
  • Implement link shortcuts to Tickets (#{ticket_id} -> /~{user_or_team}/{current_repo}/tickets/{ticket_id}) and Patch Proposals (!{patch_proposal_id} -> /~{user_or_team}/{current_repo}/patches/{patch_proposal_id})
  • Add dynamic robots.txt that echoes back the user-agent and tells to limit to 2 req/s
  • Add flood protection/mitigation

/ (index)

  • have a landing page that explains what this Frogue instance is about.
    • Have a link to login
    • If registrations are open, have link to register
  • if we are logged in, show the user's Feed? like what a logged in Mastodon/snac/others user would see, but with ForgeFed additions (external activity on the user's repo/tickets/patches)?
    • show AP feed
    • show instance/forgefed feed

/~{user_or_team}

Profile page for a user.

Registration

  • implement open registration (/register)
  • implement invite-only registration
    • environment variable $FROGUE_REGISTRATION_MODE="open" or $FROGUE_REGISTRATION_MODE="invite_only" to configure the server. defaults to open.
    • when the DB has no users, the first user registration is open.
    • the user can generate an invite link that is valid $FROGUE_INVITES_VALIDITY_SECONDS, defaults to 48 hours. The user then gives it to someone. A user can only generate $FROGUE_INVITES_ALLOWED_PER_DAY links per day, defaults to 5. The invite link is something like /register/?invite={UUID} where UUID is checked against DB for validity.

Profile page

  • view / list current repos
    • order current repos by last activity (creation order for now)
  • edit profile
  • Show latest user Notes/Announces
  • create new repository
    • fix the out-of-alignement radio buttons on the new repository page

Federation

This is an ActivityPub-compatible stream of messages and updates related to the user. Same for a repository.

  • ActivityPub actor keys are RSA-2048; move to 4096 (or Ed25519 where peers support it). Needs is a key rotation mechanism

  • ActivityPub Actor Person

  • ActivityPub Notes

  • ActivityPub reactions (Announce/Like/EmojiReact, …)

    • Outgoing EmojiReact on remote notes
  • Unified outbound HTTP signing (sign_post/sign_get helpers)

  • Remote actor cache populated with name/preferred_username fields

  • Remote actor cache refresh policy (24h staleness check)

  • Webfinger and remote actor discovery by handle (@user@host)

  • Follow remote actors with Accept/Reject handling

  • Receive and store remote notes from followed actors

  • Logged-in home feed with remote notes

  • Federate reactions on remote notes

  • Phase 0: Unified outbound HTTP signing and remote actor cache improvements

  • Phase 1: Webfinger-based remote actor discovery and SSRF protection

    • Fix SSRF DNS-rebinding TOCTOU: DNS is checked before request but could change between check and actual request
  • Phase 2: Follow remote actors with Accept/Reject handling

  • Phase 3: Receive and store remote notes from followed actors

  • Phase 4: Logged-in home feed with remote notes

  • Phase 5: Federate reactions on remote notes

Repository /~{user_or_team}/{repo_slug}

  • Rename the route names:
    • /~{user_or_team}/{slug} -> /~{user_or_team}/{repository_slug}
    • /~{user_or_team}/{slug}/tree/{tail} -> /~{user_or_team}/{repository_slug}/tree/{ref_or_commit}/{file_path}
    • /~{user_or_team}/{slug}/raw/{tail} -> /~{user_or_team}/{repository_slug}/raw/{ref_or_commit}/{file_path}
  • if a user is logged in, use their username in the git URL instead of user git. Would that not conflict with the plans to have a WebUI?
  • (while we don't allow unenthicated ssh git fetches) Show the web read-only access git url instead of the ssh one if the user is unauthenticated.

Summary / Landing

  • show readme on landing
    • if the user has a favorite language set in their browser, look for a localized readme, such as README.fr.md or README_fr.md.
  • show a list of the 3 latest commited branches with their latest commit (hash,author,first line of commit message)
  • show a list of the 3 latest tags with their latest commit (hash,author,first line of commit message)
  • http git access (read-only) /{user_or_team}/{repo_slug}.git if user is unauthicated, ssh git access (read-write) if the user is authenticated.

Federation

A repository has its own ActivityPub Actor type (Repository) that people can follow for updates. We use the ForgeFed Repository type (not ActivityPub's Application type) as per the ForgeFed specification.

  • implement FF Repository
    • Note: Branch objects, repo Notes/reactions, likes/stars, tag pushes, Factory, Person sshKeys, Grants, and webfinger for repos are deferred to future work
  • implement FF TicketTracker
  • implement FF PatchTracker

Refs viewing

  • list all available refs in the repository (branches/tags)

Commit History

  • list all commits which the given ref has as ancestors.
    • Implement pagination

Diff/Single commit

  • diff viewer for a single commit.
    • when a commit hash is shown to the user, it now redirects to the diff of the given commit. On the diff page is a link to the tree of this commit.
  • diff viewer for a range of commits (/compare/{base}...{head}).
  • Add line numbers to modified files's diffs, each with an anchor you can use to link to a specific line of a file in a diff.
  • Generalize as structs the maud components used in diffs so we can re-use them in /{user_or_team}/{repo_slug}/compare/{base}...{head}
  • Side-by-side diffs?
  • "intelligent" diffs via something like delta?
  • Folding/unfolding of file headers to hide/show their diffs. All-deletion or all-creation, as well as diffs bigger than say 100 lines should be folded by default.
  • Show git stats (~modified,+added,-deleted) for commits/diffs (even for commits lists such as history?).
    • implement ~modified lines

File/tree browser at given ref/commit

  • tree browser for a given ref: walk a repository's directory tree at any branch, tag, or commit hash, and open the files in it (source colouring, markdown rendered, raw bytes on their own URL).
  • Add line numbers to viewed files, with link anchors to be able to bring attention to a specific line
  • Add HTTP caching for raw files. If the url mentions a commit directly, we can know when the file has been last modified from the date of the commit. If the url mentions a ref, the modification date is only an indirection away.

Tickets (≃ issues)

They have a summary (≃title) with markdown, a description with markdown, a list of tags applied to them, which are created by the repository owner(with default: open,closed,bug,improvement) and finally attachements (limit to smaller than 2Mb, no more than 4 per ticket (Should be configurable by an admin, via envvars for instance)).

  • list (with some tags applied by default, such as "open"?)
    • filter the list by tags
    • search (sqlite's full text search?)
    • Implement pagination
  • add
  • edit
  • delete
  • attachments (with size and count limits, configurable via envvars)
  • comments
    • FTS search
    • federation for comments (migrate comments to proper Notes)
  • state (same as patche proposals)
  • labels (same as patch proposals)

Patches/Merge requests

An other repository tab. A Patch proposal is created when someone (who can be someone other than the owner on a public repository) pushes via SSH to the special patches ref. The code is accepted and put on a special ref named patches/{patch_id}, which the user is then informed of. A Patch Proposal (PP) is created with a "draft" status, editable by the person pushing the patch (they MUST have an account to be able to push). The link to the draft PP is provided via text to the user sending the push via SSH.

A Patch Proposal (PP) is comprised of:

  • a summary (≃title)

  • a description

  • a source ref/branch (patches/{patch_id})

  • a destination branch (defaults to the repository's default_branch)

  • a status (enum: open,closed,draft,merged) (default: draft)

  • 0+ tags (maybe we could reuse the ones from the tickets? then we would need a separate "state" for tickets)

  • comments

    • FTS search?
    • federation for comments (Same: Notes)
  • A merge policy: fast-forward, fast-forward only, merge commit only, rebase-then-fast-forward

  • list PPs (with state filtering)

    • implement pagination in a second step
  • show PP detail (with diff to destination branch, of course)

  • merge action (owner-only, with conflict detection and compare-and-swap)

Repository settings

  • Repository visibility
  • label creation / deletion
  • DANGER ZONE
    • slug change
    • deletion

User settings

I think this should be something we configure via a special repository. Would be fun, no? Yeah but what about ppl that only want to report bugs?

  • SSH key WebUI

Chores

Everything that's linked to frogue's code

  • split the views module in submodules
  • Leverage the component-style UI that maud enables more
  • Change the default root data dir to something sensible, such as $XDG_DATA_DIR. (don't forget to migrate the existing DB you dumbass)