gitshark

Clone repository

git clone https://gitshark.ha1nz.de/git/workaround/Gitshark.git
git clone ssh://git@gitshark.ha1nz.de:22/workaround/Gitshark.git

← Issues

Organisations: shared repo namespace with guest/member/owner roles #1

Summary

As a user, I can create an organisation and invite other members. An organisation owns repositories just like a user does, and repo paths look identical to user paths:

  • user repo: alice/test
  • org repo: my_org/test

Because orgs and users share one URL namespace, names must be collision-checked in both directions.

Member levels

Level Rights
guest read-only (can read private org repos, no push)
member read + write (push to org repos)
owner admin (manage members, org settings, create/delete org repos, delete org)

Current state

  • users.username is unique (V1__init.sql); UsernameService rejects taken handles with UsernameTakenException (src/main/java/de/workaround/account/UsernameService.java).
  • All repo routes resolve {owner} to a User via findByUsername and Repository.owner is a User (src/main/java/de/workaround/model/Repository.java).
  • AccessPolicy (src/main/java/de/workaround/git/AccessPolicy.java) is the single authz rule set for HTTP, SSH and UI: owner-or-public.
  • Federation identifies actors by username (WebFinger, ActorUris) — org names occupy the same handle namespace.
  • Related: repository collaborators (GitHub issue #10) — same authz extension point; org membership is the org-level analogue of per-repo collaborators.

Proposed implementation

Data model

  • Organisation entity: unique name (same handle rules as usernames), displayName, createdAt.
  • OrganisationMember entity: (organisation, user, role ∈ {GUEST, MEMBER, OWNER}), unique on (organisation, user). Creator becomes OWNER. An org must always have ≥ 1 owner (block removing/downgrading the last one).
  • Repository.owner must support both owner kinds. Suggested: nullable owner_user_id + nullable owner_org_id with a CHECK that exactly one is set (avoids a polymorphic join table); unique repo name per owner either way.
  • Flyway migration V11__organisations.sql (or next free number).

Name collision check

  • One shared handle namespace: creating an org checks users.username AND organisations.name; picking a username during onboarding (and any future rename) checks organisations.name too.
  • Extract the validation into a shared service (extend UsernameService into a handle service) so both paths use identical rules and error messages.
  • Enforce at DB level as well as app level (app check + unique indexes; a cross-table exclusion needs the app-level check to be authoritative, wrapped in the same transaction).

Routing

  • {owner} path segment resolves to user first, then org (names can't collide, so order is only a lookup detail). Applies to repo pages, git smart HTTP and SSH path parsing.

Authorization (AccessPolicy)

  • canRead: also true for org repos when the user is guest/member/owner of the owning org.
  • canWrite: also true for org members with role MEMBER or OWNER.
  • Repo admin actions (delete, settings): org OWNER only.
  • HTTP, SSH and UI all flow through AccessPolicy, so git operations follow automatically.

UI

  • "New organisation" action (e.g. from the home page next to "New repository"): form with org name, collision-checked.
  • Org page at /{org}: repo list (visibility-filtered like user profiles).
  • Org settings → Members (org owners only): add user by username with role select, change role, remove member. Errors: unknown username, already a member, last owner.
  • "New repository" flow gains an owner selector: personal or any org where the user is OWNER (or MEMBER — decide; suggest OWNER-only for v1).

Out of scope (v1)

  • Federation actors for orgs (WebFinger/ActivityPub org actor) — namespace is reserved by the collision check, actor support later.
  • Teams, per-repo overrides inside orgs, org avatars, transferring repos between owners, email invitations with accept/decline (adding is immediate, like the collaborators feature).

Acceptance criteria

  • [ ] User can create an org; creator becomes owner; org repo lives at /{org}/{repo}.
  • [ ] Creating an org with an existing username (or org name) fails with a clear error; picking a username matching an existing org name fails likewise.
  • [ ] Org owner can add/remove members and change roles via UI; last owner cannot be removed or downgraded.
  • [ ] guest: can read private org repos (UI + clone via HTTP/SSH), cannot push.
  • [ ] member: can push (HTTP/SSH); non-members cannot access private org repos.
  • [ ] owner: can manage members, create and delete org repos.
  • [ ] Failing tests first (handle-collision service, AccessPolicy roles, routing resolution, resource tests), green after implementation.
  • [ ] Docs updated in the same PR: docs/users/ (orgs guide), docs/admins/ (new tables), root README.md feature list; docs/maintainers/ if federation namespace reservation is documented there.

Migrated from https://github.com/workaround-org/git-shark/issues/12 Migrated from https://gitshark.ha1nz.de/repos/miggi/GitShark/issues/1 (original author: miggi, created 2026-07-09)

Keyboard shortcuts

?Show this help
g hGo home
EscClose dialog