SPEC_SIAOHUB.md
SiaoHub — spec
What this covers: SiaoHub's visibility model, feature scope and testing approach. This file is the spec until a real issue tracker exists.
For what is built, deployed or reachable, see ClaudeDocs/HANDOFF.md —
status deliberately does not live here.
⚠️ Parts of this spec are superseded by
SPEC_ACCOUNTS.md. The auth model here (Forgejo OAuth2 as SiaoHub's identity provider, Google added later inside Forgejo), user story 7 ("a logged-in user can clone any general-visibility repo"), and the clone-approval mechanism (adding a Forgejo collaborator) have all been replaced. Identity now comes from Logto ataccounts.siao.ai; Forgejo is never an identity provider and is never exposed publicly; registration grants browsing only and cloning always requires explicit per-repo approval; clone is served by a SiaoHub-side read-only git smart-HTTP proxy. Do not implement the auth or clone-gating decisions below — readSPEC_ACCOUNTS.mdfirst. Everything else in this spec (visibility tiers via repo topics, the preview tier,resolveRepoVisibilityas the single seam, approval being SSH-only, deployment and pipeline gating) is still in force.
Problem Statement
The owner self-hosts a Forgejo instance at git.siao.ai, but has
deliberately kept it offline since seeing its stock, un-reskinned UI —
it doesn't match the "private GitHub" experience they want, and
Forgejo's own template system participates directly in that UI, which
the owner does not want touched or extended long-term (see
NOTES_GIT_SERVER.md §5 for the abandoned reskin-the-templates
attempt). Visitors who land on git.siao.ai today would see either a
login page or Forgejo's default UI — neither is acceptable as the
public face of the domain, and neither gives the owner the fine-grained,
per-repo visibility control (public / preview-only / fully restricted)
that some of the repos need.
Solution
Build SiaoHub, a self-authored Next.js (TypeScript) frontend that
is the only UI surface at git.siao.ai. Forgejo continues running,
but purely as a git-hosting and API backend — none of its own templates
or pages are ever shown to a visitor. SiaoHub talks to Forgejo's API and
to Forgejo's OAuth2 provider for authentication, and implements its own
tiered visibility model on top of a simple, Forgejo-native tagging
convention (repo topics), so the rules live next to the repos they
govern rather than in a second system that can drift out of sync.
User Stories
- As an anonymous visitor, I want to land on
git.siao.aiand see a list of public repos, so that I get the "browsable GitHub-like site" experience instead of a login wall. - As an anonymous visitor, I want to open a general-visibility repo and read its full file tree and file contents, so that I can evaluate the code without needing an account.
- As an anonymous visitor, I want a rendered
READMEwhen I open a repo, so that I get the same at-a-glance context GitHub gives me. - As an anonymous visitor, I want to browse a repo's commit history and view a diff for any commit, so that I can understand its evolution without cloning it.
- As an anonymous visitor opening a repo tagged as sensitive
(
visibility:preview), I want to see only the first 10 lines of any file, so that the owner can share a limited preview without exposing the full source. - As an anonymous visitor, I want the clone/download affordance to be absent or disabled unless I'm logged in, so that read access and copy access are clearly different privilege levels.
- As a registered (logged-in) user, I want to clone any general- visibility repo, so that I can pull the code locally.
- As a registered user, I want repos tagged as sensitive to still be gated behind the owner's manual approval even after I log in, so that "logged in" and "cleared for this specific sensitive repo" stay distinct.
- As the owner, I want to log in via my existing Forgejo account (OAuth2), so that SiaoHub doesn't require a second, separately-maintained credential store.
- As the owner, I want to later add Google as a login option, so that trusted collaborators can sign in without a Forgejo-native account — without SiaoHub's own code needing to change (the OAuth source is added at the Forgejo layer).
- As the owner, I want to mark a repo's visibility tier by adding a
visibility:<tier>topic to it in Forgejo, so that I manage sensitivity from a tool I already use daily, without a separate admin panel. - As the owner, I want to be able to introduce new visibility tiers later (beyond just "public" and "preview") by adding a new topic name and a corresponding rule in SiaoHub's config, so that the system grows without a schema migration or new UI.
- As the owner, I want the mapping from
visibility:<tier>topics to display rules to live in server-side config that only someone with SSH/localhost access can edit, so that no web-reachable account — including my own — can silently change what a tier means. - As the owner, I want approving a clone request for a sensitive repo to be a manual, SSH/localhost-only action (adding a person as a Forgejo collaborator or issuing them access directly), so that a compromised web session can never grant clone access on its own. There is deliberately no "approve" button anywhere in the SiaoHub web UI, not even in an owner-authenticated view.
- As the owner, I want SiaoHub deployed on the same host as Forgejo,
wired into the existing
git-siao-aidocker-compose + Cloudflare Tunnel pipeline, so that API calls from SiaoHub to Forgejo stay on localhost and I don't maintain a second deployment mechanism. - As a developer working on SiaoHub, I want a unit-test suite covering every branch of the visibility-resolution logic (tier × auth state), so that a permissions regression is caught before it ships.
- As a developer working on SiaoHub, I want Playwright end-to-end coverage of the actual user-visible paths (anonymous browse, preview- only truncation, logged-in full view, clone affordance visibility), so that a broken permission boundary is caught even if the unit tests miss it.
- As the owner, I want tests to run and gate at every stage — on commit/push (unit tests), on PR/personal review (full suite), on internal/staging deploy (smoke test against the real deployed environment), and again before the real public deploy — so that no stage is a rubber stamp.
- As the owner, I want the new SiaoHub repo's branch protection to
require the test check with
enforce_admins: truefrom day one, so that thesiao.airepo's known bypass (an admin token can push past a required check) isn't repeated on a project where the stakes are a permissions bug, not a cosmetic one. - As the owner, I want the visual identity to be its own thing —
monospace type for code, sans-serif for interface chrome, a sage-
green accent,
#FAFAFAlight background carried over from the homepage, and a dark mode that's a deep, layered gray (not pure black) — so that SiaoHub reads as GitHub-inspired tooling, not a skin of the homepage and not a pixel clone of GitHub itself. - As the owner, I want issue tracking, PRs, and multi-user collaboration features left out of the first version, so that effort goes toward the single-user "browse my own code" experience first, since that's the actual current use case.
Implementation Decisions
- Frontend: Next.js, TypeScript. Deployed on the same host as the
Forgejo container, added to the existing
git-siao-aidocker-compose stack and reachable through the existing Cloudflare Tunnel. No Cloudflare Pages/Workers edge runtime — SSR needs full Node compatibility (OAuth token exchange, server-side API calls to Forgejo), which edge runtimes only partially support. - Backend: Forgejo, unchanged, used purely as a git host + REST API
- OAuth2 provider. None of Forgejo's own templates/pages are ever
rendered to a visitor. No Forgejo template modifications (the earlier,
abandoned reskin-the-templates approach in
NOTES_GIT_SERVER.md§5 stays abandoned).
- OAuth2 provider. None of Forgejo's own templates/pages are ever
rendered to a visitor. No Forgejo template modifications (the earlier,
abandoned reskin-the-templates approach in
- Auth: Forgejo OAuth2 as the identity provider for SiaoHub's login flow. Google is added later as an external OAuth2 source inside Forgejo itself (Forgejo's own "sign in with Google" support) — SiaoHub's code does not need to change when that happens, since it only ever talks to Forgejo's OAuth2 endpoint.
- Visibility tiers: encoded as Forgejo repo topics using a
visibility:<tier>naming convention (e.g.visibility:preview). No topic present = default general-visibility tier. The mapping from topic name to display rule (what "preview" means: first 10 lines, no clone) lives in a small server-side config object in the SiaoHub codebase/deployment config — not a database, not an admin UI. Adding a new tier is: (1) apply the new topic to a repo in Forgejo, (2) add its rule to this config, redeploy. - Central visibility seam: a single resolution function/module,
resolveRepoVisibility(repo, session) → { canBrowse, canClone, previewOnly, previewLineLimit }(exact naming TBD at implementation time), used by every page and API route that touches repo content. This is the one seam in the system — no page or API route implements its own ad hoc visibility check. - Clone approval for sensitive repos: manual only. The owner grants access via SSH/localhost (e.g. adding the requester as a Forgejo collaborator directly, or issuing a scoped token) — this is explicitly not wired into any SiaoHub web UI, including owner-authenticated views. No "pending requests" approve/deny control exists in the app for this version.
- MVP feature scope: repo list (home), file browser (tree + file view with syntax highlighting + rendered README), commit history + per-commit diff view. No issues, no PRs, no search, no multi-user profile pages in this version.
- Naming: "SiaoHub" — provisional, cheap to rename later, not a blocking decision.
- New repo hygiene: branch protection with
enforce_admins: truefrom the first commit (contrast withshihte/siao.ai, which currently hasenforce_admins: falseand was bypassed once by an admin-token push around a required check).
Testing Decisions
- Good tests here means: test what a visitor or the owner can actually
observe (rendered content, clone affordance presence, HTTP response
shape) — not the internal shape of
resolveRepoVisibility's intermediate calculations. - Unit/integration tests (Vitest or Jest — TBD at implementation
time, no strong prior constraint): every branch of
resolveRepoVisibility— general repo × anonymous, general repo × logged-in, preview-tier repo × anonymous, preview-tier repo × logged-in-but-not-approved. This is the highest-value test target in the whole project, since a missed branch here is a disclosure bug, not a cosmetic one. - End-to-end tests (Playwright — same tool
siao.aialready uses, seeNOTES_HOMEPAGE.mdfor existing conventions): anonymous browsing of a public repo's tree/file/README, anonymous view of a preview-tier repo showing only 10 lines, logged-in full view of both tiers, clone control visible/hidden in each of the above states. - Pipeline gating, all four stages real (not advisory):
- commit/push → unit tests only, fast feedback
- PR / personal review → full suite (unit + Playwright)
- internal/staging deploy → smoke-test suite run against the actual deployed staging environment (catches deploy-shape issues, not just logic issues)
- production deploy → final gate, blocks the deploy on failure
- Branch protection enforced for everyone, including the owner's admin
account (
enforce_admins: true), unlike the existingsiao.airepo.
Out of Scope
- Issues, pull requests, code review comments, notifications, org/team pages, in-app search — none of this ships in the MVP.
- A web-based approval UI for sensitive-repo clone requests — approval stays SSH/localhost-only by design, not a temporary gap.
- A general-purpose admin panel for editing visibility-tier rules — that config is server-side and edited directly, on purpose.
- Rewriting or reskinning Forgejo's own templates — SiaoHub replaces the UI surface entirely instead.
- Migrating
git.siao.ai's live/offline decision — bringing the tunnel back up is a separate, owner-gated decision already documented inHANDOFF.md, unaffected by this spec.
Further Notes
- This spec assumes the current
git.siao.aiinfra described inNOTES_GIT_SERVER.md§7–9 (sudo-less, self-deploying via a systemd path unit watching a Forgejo-container-side hook) — SiaoHub's own service should be added to that samedocker-compose.ymland ride the same deploy mechanism, not a new one. - The tunnel is currently deliberately offline (owner rejected the stock
Forgejo UI on sight) — SiaoHub existing and looking right is the
actual precondition for bringing it back up. Don't re-enable the
tunnel as part of implementing this spec without checking with the
owner first; that's a separate decision documented in
HANDOFF.md. - No issue tracker exists yet for a "SiaoHub" project (it isn't a repo
yet), and
ready-for-agent-style triage labels haven't been set up anywhere for it. This file stands in for that until a real repo/tracker exists — move the content there rather than duplicating it once it does.