.gitbay/wiki/Parity.org
375 lines · 18745 bytes
Parity
- Rule
- Merge requests
- Issues
- Repositories
- Discovery
- Accounts
- Organizations
- Pagination
- SSH only, by design
Which surface can do what. The CLI is meant to be the complete interface: every capability exists over SSH, and the other surfaces dispatch the same control commands rather than reimplementing them, so they cannot drift. This page is updated in the merge request that changes a row.
Three surfaces now: the CLI over SSH, the web, and the iOS client
(krz/gitbay-ios). A no in the cli column is a defect, not a
preference — it means some surface reached around the registry and
stranded a capability where only it can reach.
Rule
A capability lands over SSH first. If it belongs to the
triage/review/respond loop, it lands on the web in the same merge
request. Anything whose input is a credential — secrets, mirror
tokens, API tokens — stays SSH-only by design: the web dispatcher
refuses SSHOnly commands outright. Session minting is not one of
them: what a browser submits to ask for a login link is a username or
an address, and the credential it gets back travels by mail.
Rows are one page or one action each. Grouped rows hide gaps, twice now: "browse, log, blame, search" read as covered while blame had no command at all, and "build list, log" read as covered while the job list a trigger can name had none (krz/gitbay#50), leaving the picker browser-only and the iOS build screen unable to say more than the log.
Merge requests
| capability | cli | web | ios |
|---|---|---|---|
| read, diff, commits | yes | yes | yes |
| review and check times | yes | yes | yes |
| who resolved it, when | yes | yes | yes |
| comment | yes | yes | yes |
| edit title and body | yes | yes | yes |
| review (approve etc.) | yes | yes | yes |
| resolve a thread | yes | yes | yes |
| comment on a diff line | yes | yes | yes |
| merge (all strategies) | yes | yes | yes |
| close | yes | yes | yes |
| create | yes | yes | yes |
| draft, ready | yes | yes | yes |
| search title and body | yes | yes | yes |
| create from a fork | yes | yes | yes |
| retarget | yes | yes | yes |
| milestone | yes | yes | yes |
| request a review | yes | yes | yes |
| choose body markup | yes | yes | yes |
| stacked merge requests | yes | yes | yes |
| revisions | yes | yes | yes |
| range-diff | yes | no | yes |
| merge gates | yes | yes | yes |
Reviews and checks carry the time they last said something, and a
ci/<job> check carries how long its build ran, so a merge request
reads without opening the build. Statuses posted through status set
have no build and report only the time. A merged or closed merge
request names who resolved it and when; a row without that stamp — a
migrate import, or one merged before krz/gitbay!137 with no
mr.merged event to backfill from — says neither rather than
inventing a time.
A merge request whose target is another open merge request's source
branch is stacked on it: mr show and the page say so both ways, and
when the lower one merges, everything stacked on it is retargeted onto
what it merged into with its reviews kept. A squash or rebase merge is
refused while anything is stacked on the merge request, since it would
rewrite the commits the stack builds on. All three surfaces show the
stack both ways.
A draft merge request is open but not asking: it does not merge, and it
does not appear in anyone's review queue. Draft is a flag rather than a
fifth state, so every state = 'open' rule still means what it did.
mr revisions lists the heads a merge request has had; the web page
lists them beside the reviews they staled, and the iOS client has a
Revisions section. mr range-diff compares two heads: the iOS client
shows it from a revision to the one before, as text; the web has no
view. Batched review is not built.
mr review request --add <user> asks a particular person, who then
carries the merge request in their queue and is notified; --remove
withdraws the ask. Without one the queue is computed from involvement —
what you own, are granted, or reach through an org or team — so a
collaborator with write access who has not touched a thread hears
nothing until they do (krz/gitbay#145).
Creating from a fork works anywhere the source can be typed as
owner/name:branch. The web's source picker offers the branches of
every fork the viewer can push to in that form, and the repository
header has the fork control, so the whole path — fork, edit a file,
propose — runs in a browser. Retargeting moves an open
merge request onto another branch of the same repository and stales the
reviews, since an approval was of the diff against the old branch.
Issues
| capability | cli | web | ios |
|---|---|---|---|
| read, list, filter | yes | yes | yes |
| filter by label, assignee, author, milestone | yes | yes | yes |
| search title and body | yes | yes | yes |
| create | yes | yes | yes |
| comment | yes | yes | yes |
| edit title and body | yes | yes | yes |
| close and reopen | yes | yes | yes |
| labels, assignees | yes | yes | yes |
| milestone | yes | yes | yes |
| milestone list | yes | yes | yes |
| labels: list, colour | yes | yes | yes |
| choose body markup | yes | yes | yes |
| issue templates | yes | yes | yes |
| milestone create, close, reopen | yes | no | yes |
| org labels: set, list, remove | yes | list | no |
| org milestones: create, list, close, reopen | yes | list | no |
| closes across repositories | yes | yes | yes |
Labels are created on the fly by issue label --add and managed by
label list, label set <label> --color rrggbb and label remove,
which takes the label off every issue. The web paints the stored colour
on every chip and derives one from the name when none is set. The set
itself is at /<owner>/<repo>/labels, linked from the issue list:
create, recolour and remove, dispatching the same commands.
Org labels and milestones are managed on the CLI and API only;
/<org>/-/labels and /<org>/-/milestones show them. The repository
label page's form exists for colour alone, and three org forms nobody
asked for were not worth their handlers.
Issue, MR and release bodies, and their comments, carry the markup they
were written in — --format md|org on create, comment and edit, stored
alongside the text so changing a preference later cannot reinterpret
prose that already exists. Every surface renders the stored format, and
every surface now offers the choice: the web's create forms, and the iOS
composer on create, edit and comment. An edit starts on the format its
body was stored in, since starting elsewhere would silently reinterpret
it on the next save. Diff-line comments have no format column and are
always markdown.
Repositories
| capability | cli | web | ios |
|---|---|---|---|
| browse files | yes | yes | yes |
| read a file | yes | yes | yes |
| commit log | yes | yes | yes |
| commit log at a ref | yes | yes | yes |
| one commit with its patch | yes | yes | yes |
| blame | yes | yes | yes |
| search file contents | yes | yes | yes |
| compare two refs | yes | yes | yes |
| branches and tags | yes | yes | yes |
| wiki (read) | yes | yes | yes |
| download an archive | yes | yes | n/a |
| edit a file | yes | yes | yes |
| create | yes | yes | yes |
| fork | yes | yes | yes |
| pin | yes | yes | yes |
| bookmark | yes | yes | yes |
| bookmark list | yes | yes | yes |
| watch, unwatch | yes | yes | yes |
| mute | yes | no | yes |
| settings, protection | yes | yes | yes |
| default branch | yes | yes | yes |
| merge requests only | yes | yes | yes |
| protected tags | yes | yes | yes |
| require codeowners | yes | yes | yes |
| access grants | yes | no | yes |
| effective access | yes | no | yes |
| webhooks | yes | no | yes |
| runners attach, list, detach | yes | yes | n/a |
| import from a remote | yes | no | yes |
| topics, website | yes | yes | yes |
| visibility | yes | yes | yes |
| archive (read-only flag) | yes | yes | yes |
| release list, show | yes | yes | yes |
| atom feeds | n/a | yes | n/a |
| release create, edit | yes | yes | yes |
| build list | yes | yes | yes |
| build show (one build) | yes | yes | yes |
| build log | yes | yes | yes |
| build jobs | yes | yes | yes |
| build trigger | yes | yes | yes |
| build cancel | yes | yes | yes |
| job image (ci.yml) | yes | n/a | n/a |
| dependency checks on/off | yes | yes | yes |
| dependency status | yes | yes | yes |
| delete, transfer | yes | no | no |
| rename | yes | no | yes |
| release delete | yes | yes | yes |
| release asset add | yes | no | n/a |
| release asset remove | yes | no | yes |
No row is web-only any more. Blame, file editing, log at a ref, archive, the public listing and the wiki were all in that state — a handler reading git or the store directly instead of dispatching a command — until krz/gitbay!99, !101 and !102 gave them commands.
build cancel withdraws a queued build, or ends a running one: the
server closes the runner's log session and the runner kills the step
within a couple of seconds. Cancelling a duplicate of a commit that
already passed the job puts that result back on the commit. The build
page carries the button while a build is still cancellable.
A pin and a bookmark are different things and are stored separately. A pin is private quick access to what you are working on, and drives the rail; a bookmark is public, says a repository is worth coming back to, and its count is the only popularity signal on the instance. Bookmarking needs read access only — it is something you do to someone else's repository — and a repository bookmarked while public and since made private drops out of the listing rather than leaking that it exists (krz/gitbay#146).
The web's watch and pin controls write the store directly instead of
dispatching repo watch and repo pin. That is why the web cannot
mute: its toggle knows watching and default only.
Dependency checks are off until a repository's admin turns them on: the
check tells a public registry what the repository depends on. repo deps
status lists what is behind; the repository's settings page renders the
same report under the toggle — last check, last error, the tracking
issue, and the rows. The issue the worker opens, rewrites and closes is
still the copy every other surface reads.
The wiki row covers reading. A wiki lives at .gitbay/wiki/ on the
default branch, so editing one is editing a file in the repository —
a push, or repo commit-file — and there is no wiki-specific edit row
to have parity on. The web editor reaches it on any repository that
permits server-authored commits; one requiring verified signatures
does not, because the server signs nothing on a user's behalf, so
those wikis are push-only.
n/a marks a capability deliberately absent from a surface rather than
missing from it. Archive download is n/a on iOS: the read API carries
a command's stdout as a JSON string, so a gzip stream cannot survive it,
and the app has nowhere useful to put a tarball — the brief rules out
local git, so there is no clone, checkout or build to feed. The web's
route stays the way to get one. release asset add is n/a on iOS for
the same reason from the other direction: the file arrives on stdin,
which the API carries as a JSON string. Attaching a runner is n/a on
iOS for a plainer reason: the key is generated by gitbay-runner init
on the machine that will run builds, and that machine's terminal (the
command init prints) or the settings page is where the paste happens.
A phone has neither the key nor the runner.
A README or wiki page's org renders per surface: the web through
go-org, the iOS client through the shared OrgSwift package
(krz/org-swift). OrgSwift is held to orgo's output by the
krz/org-conformance corpus — golden renderings from orgo, itself
diffed against Emacs ox-html — so constructs the iOS client used to
approximate (tables, footnotes, timestamps, heading tags, nested lists)
now render the way the reference does. go-org is not yet on the corpus.
Discovery
| capability | cli | web | ios |
|---|---|---|---|
| search repositories | yes | yes | yes |
| search issues and merge requests | yes | yes | yes |
| browse all public repositories | yes | yes | yes |
| profile page | yes | yes | yes |
| profile about and links | yes | yes | yes |
| activity feed | yes | yes | yes |
| command reference | yes | no | n/a |
explore is the listing without a query; repo search is the one with.
search is both plus the title and body of every issue and merge
request the caller can read, over FTS5; the web serves it at /search
with a field in the rail, and an anonymous visitor gets the public rows
from the same query. issue list --search and mr list --search narrow
one repository. What someone types is quoted term by term, so an FTS5
operator — c++, AND, a lone quote — is a word to match and never a
syntax error. repo grep remains the per-repository file-contents
search.
About text renders as markdown or org-mode per the about_format it
was stored with. The iOS client decodes and renders both,
through the same OrgSwift path a README takes.
help lists the command registry. Bare it is an index, one line per
command, sorted. With a prefix (help mr) it adds each command's
argument syntax, which is the only place flags are written down;
gitbay <cmd> --help asks the server for the same thing, and --json
returns {path, summary, usage}. No web page renders it, and a native
client has no use for one (krz/gitbay#57).
Accounts
| capability | cli | web | ios |
|---|---|---|---|
| SSH keys: list, add, remove | yes | yes | yes |
| SSH key label | yes | yes | no |
| PGP keys: list, add, remove | yes | yes | yes |
| email add and verify | yes | yes | yes |
| email list, remove, primary | yes | yes | yes |
| dashboard aggregate | yes | yes | yes |
| notification inbox | yes | yes | yes |
| activity mail on, off | yes | yes | yes |
| watch writable repos | yes | yes | no |
| API token mint | yes | no | no |
| account export bundle | yes | yes | n/a |
| profile set | yes | yes | yes |
| request a login link | n/a | yes | n/a |
| account import bundle | yes | no | n/a |
Notifications land in an inbox row per recipient whether or not the
instance sends mail, and mail is the second half when SMTP is
configured. notifications list reads it, unread by default;
notifications read <id>... | --all clears it; the dashboard and the
web rail carry the unread count. repo watch adds you to a
repository's notifications, repo mute silences it, and repo unwatch
returns you to the default from either — told about work you are part
of, nothing more. notifications settings watch on widens that default
to every repository you can write to, without a row per repository. A
mute wins over owning the repository, having written the thread, or the
preference.
A login link is requested from the login page by username or verified
address, and arrives by mail: it works once and expires in fifteen
minutes. The row is n/a for the CLI because a terminal with a
registered key runs web login, which mints a link directly and needs
no mail. It exists because an account with no SSH key had no way into
the web at all (krz/gitbay#155). The page offers the form only when the
instance has SMTP configured; there is no separate switch. The response
never says whether the account exists. It is n/a on iOS for the same
reason it is on the CLI, from the other end: the app authenticates with
a bearer token pasted at sign-in, so a one-time link into the web
unlocks nothing it can use.
The account export bundle is n/a on iOS on the archive-download
argument above — a JSON bundle has nowhere useful to land on a phone,
and the web route stays the way to get one.
profile set carries description, website, about and links. It is not
SSHOnly — nothing about a bio is a credential, and the JSON API runs
it. The account settings page has the form, and so does the iOS client:
--link replaces the whole set rather than appending, so a client sends
every link it keeps on every save, and --link '' is how they are
cleared.
Organizations
| capability | cli | web | ios |
|---|---|---|---|
| read members and teams | yes | yes | yes |
| members add, remove, role | yes | yes | yes |
| teams create, delete | yes | yes | yes |
| team members | yes | yes | yes |
| team repo grants | yes | yes | yes |
| create, rename | yes | yes | yes |
| delete | yes | n/a | n/a |
| profile | yes | no | yes |
Pagination
issue list, mr list, repo list, and feed take --limit <n>
and --cursor <c>. Cursors are opaque; each page carries the next
one. Without the flags a list stays complete, so existing scripts are
unchanged. The web pages the issue and merge request lists at fifty
with the same cursors; iOS pages with them too.
SSH only, by design
Build secrets, mirror configuration and tokens, custom domain claims, API token minting, web session listing and revocation, deploy keys, account and instance administration. Deleting, transferring or renaming a repository is also CLI-only, as is deleting an organization: each removes or moves what clone URLs point at, and wants a typed command, not a button.
These are the only rows where a no is intended. Everywhere else a
no is work outstanding, and n/a means a surface cannot usefully
carry the capability at all — see the archive note above.