Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

#223

Customize the instance from an instance repository

merged · by keenan 1d ago · merged into main at 6ce635a8 by keenan 1d ago

keenan opened this 1d ago

Why

Customizing an instance meant editing vole.toml on the host and restarting, and the packaged service cannot write that file (ProtectSystem=strict). Custom CSS, a favicon, and static assets had nowhere to live at all. The landing page’s prose was the one thing an admin could change from the browser, but it was stored in the instance database rather than with the rest of the customization.

This replaces that with one repository, modelled on GitHub’s .github: fixed paths read as data. There is no template language, no code execution, and no trust flag to enable.

Scope

  • forge/instancerepo: reads one commit into an immutable snapshot on a two second timer and swaps it atomically. A request never runs git; a load failure keeps the previous theme; the repository is hidden from the home grid and activity rail.
  • Fixed paths: profile/README.md (introduction), profile/private/README.md (signed-in viewers), profile/custom.css, profile/favicon.svg, and assets/ served at /static/custom/assets/. Unknown files are ignored.
  • Markdown goes through the issue sanitiser; assets are an extension whitelist with per-file, total, and count caps. HTML and scripts are not assets. SVG responses carry a sandboxing CSP.
  • The home pencil keeps the in-place editor, but a save is now a commit to profile/README.md with the admin as the author and web.home.intro in the audit log. It always writes the public file, even when a private README is what the admin is reading.
  • Admin → Configuration grows an Instance repository panel: name, loaded commit, last load error, clone URL, recognized paths, and a Create instance repository button that scaffolds the starter files. An existing empty repository is finished rather than rejected.
  • instance_repo (default vole-instance, empty disables) and instance_name is the heading. Removes the pending introduction-store change (#222, closed in favour of this).
  • The rest of the landing page keeps its original shape: heading, introduction card, repository grid, Latest rail. The per-card commit line, repository/activity summary, tagline setting, repository search bar, and top-languages block are gone.

Acceptance criteria

  • An instance admin can write or clear the introduction without touching the config file or restarting; the save is a commit.
  • A visitor sees the sanitized public README, custom CSS, favicon, and assets; a signed-in viewer sees the private README when one exists.
  • A non-admin cannot edit, push, or read the instance repository, and it never appears as a project.
  • A broken theme keeps the previous snapshot and reports the error only to the admin.
  • instance_name names the heading; an unset value shows Vole.
  • No search bar, top-languages block, or tagline on the home page.

Testing

./vole workflow run verify: formatting, vet, build, license/NOTICE, govulncheck, packaging, deployment files, markdown links, and the full -race suite pass.

New coverage: forge/instancerepo (fixed paths, ignored files, extension whitelist, oversized file), server/instance_repo_test.go (public/private README, CSS/favicon links, asset serving and script rejection, hidden repo, admin scaffold, editor availability), and the rewritten server/landing_test.go (editor commits the public README, clears it by deleting the file, audits, sanitizes, rejects oversized input, admin-only).

Discussion (0)

No discussion yet.