.gitbay/wiki/Parity.org

v1.42.0
gitbay/.gitbay/wiki/Parity.org rendered · source · history · blame · raw

542 lines · 27964 bytes

  1#+title: Parity
  2
  3Which surface can do what. The CLI is meant to be the complete
  4interface: every capability exists over SSH, and the other surfaces
  5dispatch the same control commands rather than reimplementing them, so
  6they cannot drift. This page is updated in the merge request that
  7changes a row.
  8
  9Three surfaces now: the CLI over SSH, the web, and the iOS client
 10(krz/gitbay-ios). A =no= in the cli column is a defect, not a
 11preference — it means some surface reached around the registry and
 12stranded a capability where only it can reach.
 13
 14* Rule
 15
 16A capability lands over SSH first. If it belongs to the
 17triage/review/respond loop, it lands on the web in the same merge
 18request. Nothing is held back from a surface any more (#234): the
 19registry has no flag for it, and what a caller may do is the account's
 20rights narrowed by the scope of the key or token it arrived with,
 21decided in one place. A =no= in the web or ios column is a page nobody
 22has built yet, not a refusal.
 23
 24Rows are one page or one action each. Grouped rows hide gaps, twice
 25now: "browse, log, blame, search" read as covered while blame had no
 26command at all, and "build list, log" read as covered while the job
 27list a trigger can name had none (krz/gitbay#50), leaving the picker
 28browser-only and the iOS build screen unable to say more than the log.
 29
 30* Merge requests
 31
 32| capability             | cli | web | ios |
 33|------------------------+-----+-----+-----|
 34| read, diff, commits    | yes | yes | yes |
 35| review and check times | yes | yes | yes |
 36| who resolved it, when  | yes | yes | yes |
 37| comment                | yes | yes | yes |
 38| react to it or a comment | yes | yes | no  |
 39| edit title and body    | yes | yes | yes |
 40| review (approve etc.)  | yes | yes | yes |
 41| resolve a thread       | yes | yes | yes |
 42| comment on a diff line | yes | yes | yes |
 43| suggest a change       | yes | yes | no  |
 44| apply a suggestion     | yes | yes | no  |
 45| merge (all strategies) | yes | yes | yes |
 46| merge when ready, cancel | yes | yes | no  |
 47| close                  | yes | yes | yes |
 48| close in favour of another | yes | yes | yes |
 49| create                 | yes | yes | yes |
 50| draft, ready           | yes | yes | yes |
 51| search title and body  | yes | yes | yes |
 52| create from a fork     | yes | yes | yes |
 53| retarget               | yes | yes | yes |
 54| milestone              | yes | yes | yes |
 55| labels                 | yes | yes | yes |
 56| filter by label        | yes | yes | yes |
 57| request a review       | yes | yes | yes |
 58| choose body markup     | yes | yes | yes |
 59| preview body markup    | n/a | yes | no  |
 60| TeX math as MathML     | n/a | yes | no  |
 61| stacked merge requests | yes | yes | yes |
 62| revisions              | yes | yes | yes |
 63| range-diff             | yes | yes | yes |
 64| merge gates            | yes | yes | yes |
 65
 66Reviews and checks carry the time they last said something, and a
 67=ci/<job>= check carries how long its build ran, so a merge request
 68reads without opening the build. Statuses posted through =status set=
 69have no build and report only the time. A merged or closed merge
 70request names who resolved it and when; a row without that stamp — a
 71=migrate= import, or one merged before krz/gitbay!137 with no
 72=mr.merged= event to backfill from — says neither rather than
 73inventing a time.
 74
 75A merge request whose target is another open merge request's source
 76branch is stacked on it: =mr show= and the page say so both ways, and
 77when the lower one merges, everything stacked on it is retargeted onto
 78what it merged into with its reviews kept. A squash or rebase merge is
 79refused while anything is stacked on the merge request, since it would
 80rewrite the commits the stack builds on. All three surfaces show the
 81stack both ways.
 82
 83A draft merge request is open but not asking: it does not merge, and it
 84does not appear in anyone's review queue. Draft is a flag rather than a
 85fifth state, so every =state = 'open'= rule still means what it did.
 86=mr revisions= lists the heads a merge request has had; the web page
 87lists them beside the reviews they staled, and the iOS client has a
 88Revisions section. =mr range-diff= compares two heads: the iOS client shows it from a
 89revision to the one before, as text; the web renders the same view, with
 90a "compare to previous" link on each revision after the first. Batched
 91review — draft diff comments held with =mr comment --pending= and sent
 92together with =--comment=/=--discard= or a verdict — is built and the
 93web uses it: composing review comments before publishing them is the same
 94round trip as the CLI's =--pending= flag.
 95
 96=mr review request --add <user>= asks a *particular* person, who then
 97carries the merge request in their queue and is notified; =--remove=
 98withdraws the ask. Without one the queue is computed from involvement —
 99what you own, are granted, or reach through an org or team — so a
100collaborator with write access who has not touched a thread hears
101nothing until they do (krz/gitbay#145).
102
103Creating from a fork works anywhere the source can be typed as
104=owner/name:branch=. The web's source picker offers the branches of
105every fork the viewer can push to in that form, and the repository
106header has the fork control, so the whole path — fork, edit a file,
107propose — runs in a browser. Retargeting moves an open
108merge request onto another branch of the same repository and stales the
109reviews, since an approval was of the diff against the old branch.
110
111* Issues
112
113| capability          | cli | web | ios |
114|---------------------+-----+-----+-----|
115| read, list, filter  | yes | yes | yes |
116| filter by label, assignee, author, milestone | yes | yes | yes |
117| search title and body | yes | yes | yes |
118| create              | yes | yes | yes |
119| comment             | yes | yes | yes |
120| react to it or a comment | yes | yes | no  |
121| edit title and body | yes | yes | yes |
122| close and reopen    | yes | yes | yes |
123| labels, assignees   | yes | yes | yes |
124| milestone           | yes | yes | yes |
125| milestone list      | yes | yes | yes |
126| labels: list, colour | yes | yes | yes |
127| choose body markup  | yes | yes | yes |
128| preview body markup | n/a | yes | no  |
129| TeX math as MathML  | n/a | yes | no  |
130| issue templates     | yes | yes | yes |
131| milestone create, close, reopen | yes | yes | yes |
132| org labels: set, list, remove | yes | yes | yes |
133| org milestones: create, list, close, reopen | yes | yes | yes |
134| closes across repositories | yes | yes | yes |
135
136Labels are created on the fly by =issue label --add= and =mr label
137--add=, and managed by =label list=, =label set <label> --color rrggbb=
138and =label remove=, which takes the label off every issue and merge
139request. One set serves both. The web paints the stored colour on every
140chip and derives one from the name when none is set. The set itself is
141at =/<owner>/<repo>/labels=, linked from the issue list: create,
142recolour and remove, dispatching the same commands.
143
144Org labels and milestones are managed at =/<org>/-/labels= and
145=/<org>/-/milestones=, where org admins see the create, colour, remove,
146close and reopen forms and everyone else sees the list. The repository
147milestones page carries create, close and reopen for writers; a
148milestone the org holds shows no buttons there. Uploading a release
149asset from the releases page streams the file to =release asset add= on
150stdin, capped at =max_asset_bytes=.
151
152Issue, MR and release bodies, and their comments, carry the markup they
153were written in — =--format md|org= on create, comment and edit, stored
154alongside the text so changing a preference later cannot reinterpret
155prose that already exists. Every surface *renders* the stored format, and
156every surface now offers the choice: the web's create forms, and the iOS
157composer on create, edit and comment. An edit starts on the format its
158body was stored in, since starting elsewhere would silently reinterpret
159it on the next save. Diff-line comments have no format column and are
160always markdown. TeX math in either format renders as MathML on the
161web (#294); the terminal shows the source, so the CLI row is =n/a=.
162
163Every web form that takes markup has a Preview button beside its own
164submit: issue and merge request create, their edit and comment boxes,
165release create and edit, and the file editor on
166a path the forge renders. It posts to the form's own action, which
167renders the draft and hands the page back without writing, so what you
168see is the rendering the thread will show, autolinks included. It is a
169round trip rather than a live preview because the instance serves no
170JavaScript, the same way the blob page's rendered/source toggle works.
171The row is =n/a= on the CLI: a terminal has no form to preview, and
172=issue show= already renders. Diff-line comments are left out — they
173sit inside the diff, where a page-level preview has nowhere to go.
174
175The iOS client resolves no autolinks: =#N= and =owner/name#N= render as
176text in its threads, so a preview there will show the app's rendering
177rather than the one the web page shows.
178
179* Repositories
180
181| capability                  | cli | web | ios |
182|-----------------------------+-----+-----+-----|
183| browse files                | yes | yes | yes |
184| read a file                 | yes | yes | yes |
185| render a README             | yes | yes | yes |
186| commit log                  | yes | yes | yes |
187| commit log at a ref         | yes | yes | yes |
188| one commit with its patch   | yes | yes | yes |
189| blame                       | yes | yes | yes |
190| search file contents        | yes | yes | yes |
191| find a definition (symbols) | yes | yes | no  |
192| jump to definition from a file | n/a | yes | no  |
193| compare two refs            | yes | yes | yes |
194| branches and tags           | yes | yes | yes |
195| wiki (read)                 | yes | yes | yes |
196| download an archive         | yes | yes | n/a |
197| edit a file                 | yes | yes | yes |
198| preview an edited markup file | n/a | yes | no  |
199| create                      | yes | yes | yes |
200| fork                        | yes | yes | yes |
201| pin                         | yes | yes | yes |
202| bookmark                    | yes | yes | yes |
203| bookmark list               | yes | yes | yes |
204| bookmarks on your profile   | n/a | yes | no  |
205| watch, unwatch              | yes | yes | yes |
206| mute                        | yes | yes | yes |
207| settings, protection        | yes | yes | yes |
208| default branch              | yes | yes | yes |
209| merge requests only         | yes | yes | yes |
210| protected tags              | yes | yes | yes |
211| require codeowners          | yes | yes | yes |
212| require contexts            | yes | yes | no  |
213| access grants               | yes | yes | yes |
214| effective access            | yes | yes | yes |
215| webhooks                    | yes | yes | yes |
216| runners attach, list, detach | yes | yes | n/a |
217| import from a remote        | yes | yes | yes |
218| topics, website             | yes | yes | yes |
219| visibility                  | yes | yes | yes |
220| archive (read-only flag)    | yes | yes | yes |
221| release list, show          | yes | yes | yes |
222| atom feeds                  | n/a | yes | n/a |
223| release create, edit        | yes | yes | yes |
224| preview release notes       | n/a | yes | no  |
225| build list                  | yes | yes | yes |
226| build list paging (limit, cursor) | yes | yes | no  |
227| build row names its commit  | yes | yes | no  |
228| build list filters (ref, status, job) | yes | yes | yes |
229| build show (one build)      | yes | yes | yes |
230| build log                   | yes | yes | yes |
231| build log follow (until it ends) | yes | yes | no  |
232| build failed step, duration | yes | yes | no  |
233| build log one step          | yes | yes | no  |
234| build log tail              | yes | no  | no  |
235| build jobs                  | yes | yes | yes |
236| build trigger               | yes | yes | yes |
237| build cancel                | yes | yes | yes |
238| job image (ci.yml)          | yes | n/a | n/a |
239| dependency checks on/off    | yes | yes | yes |
240| dependency status           | yes | yes | yes |
241| delete, transfer            | yes | yes | no  |
242| rename                      | yes | yes | yes |
243| release delete              | yes | yes | yes |
244| release asset add           | yes | yes | n/a |
245| release asset remove        | yes | yes | yes |
246| snippet create, edit, delete  | yes | yes | yes |
247| snippet show, list            | yes | yes | yes |
248| snippet file set, get, remove | yes | yes | yes |
249
250No row is web-only any more. Blame, file editing, log at a ref,
251archive, the public listing and the wiki were all in that state — a
252handler reading git or the store directly instead of dispatching a
253command — until krz/gitbay!99, !101 and !102 gave them commands.
254
255=build cancel= withdraws a queued build, or ends a running one: the
256server closes the runner's log session and the runner kills the step
257within a couple of seconds. Cancelling a duplicate of a commit that
258already passed the job puts that result back on the commit. The build
259page carries the button while a build is still cancellable.
260
261A pin and a bookmark are different things and are stored separately. A
262pin is private quick access to what you are working on, and drives the
263rail; a bookmark is public, says a repository is worth coming back to,
264and its count is the only popularity signal on the instance. Bookmarking
265needs read access only — it is something you do to someone else's
266repository — and a repository bookmarked while public and since made
267private drops out of the listing rather than leaking that it exists
268(krz/gitbay#146).
269
270The web's watch and pin controls dispatch =repo pin=/=repo unpin= and
271=repo watch=/=repo mute=/=repo unwatch=, the same commands the CLI runs
272(krz/gitbay#261). The single watch button cycles default, watching and
273muted.
274
275Dependency checks are off until a repository's admin turns them on: the
276check tells a public registry what the repository depends on. =repo deps
277status= lists what is behind; the repository's settings page renders the
278same report under the toggle — last check, last error, the tracking
279issue, and the rows. The issue the worker opens, rewrites and closes is
280still the copy every other surface reads.
281
282The wiki row covers reading. A wiki lives at =.gitbay/wiki/= on the
283default branch, so editing one is editing a file in the repository —
284a push, or =repo commit-file= — and there is no wiki-specific edit row
285to have parity on. The web editor reaches it on any repository that
286permits server-authored commits; one requiring verified signatures
287does not, because the server signs nothing on a user's behalf, so
288those wikis are push-only.
289
290=n/a= marks a capability deliberately absent from a surface rather than
291missing from it. Archive download is =n/a= on iOS: the read API carries
292a command's stdout as a JSON string, so a gzip stream cannot survive it,
293and the app has nowhere useful to put a tarball — the brief rules out
294local git, so there is no clone, checkout or build to feed. The web's
295route stays the way to get one. =release asset add= is =n/a= on iOS for
296the same reason from the other direction: the file arrives on stdin,
297which the API carries as a JSON string. Attaching a runner is =n/a= on
298iOS for a plainer reason: the key is generated by =gitbay-runner init=
299on the machine that will run builds, and that machine's terminal (the
300command =init= prints) or the settings page is where the paste happens.
301A phone has neither the key nor the runner.
302
303A README or wiki page's org renders per surface: the web through
304go-org, the iOS client through the shared OrgSwift package
305(=krz/org-swift=). OrgSwift is held to orgo's output by the
306=krz/org-conformance= corpus — golden renderings from orgo, itself
307diffed against Emacs =ox-html= — so constructs the iOS client used to
308approximate (tables, footnotes, timestamps, heading tags, nested lists)
309now render the way the reference does. go-org is not yet on the corpus.
310
311* Discovery
312
313| capability                       | cli | web | ios |
314|----------------------------------+-----+-----+-----|
315| search repositories              | yes | yes | yes |
316| search issues and merge requests | yes | yes | yes |
317| saved query save, remove, pin    | yes | no  | no  |
318| saved query list and results     | yes | yes | no  |
319| pinned queries on the dashboard  | yes | yes | no  |
320| browse all public repositories   | yes | yes | yes |
321| profile page                     | yes | yes | yes |
322| profile sections as tabs         | n/a | yes | n/a |
323| profile about and links          | yes | yes | yes |
324| profile about as a file          | yes | yes | yes |
325| activity feed                    | yes | yes | yes |
326| command reference                | yes | no  | n/a |
327
328=repo symbols= and =/{owner}/{repo}/symbols= answer from the same
329store query and ranking. Jumping to a definition is a link on a name in
330the blob view, which a terminal has no place for; =repo symbols= with
331the name is its CLI form.
332
333=explore= is the listing without a query; =repo search= is the one with.
334=search= is both plus the title and body of every issue and merge
335request the caller can read, over FTS5; the web serves it at =/search=
336with a field in the rail, and an anonymous visitor gets the public rows
337from the same query. =issue list --search= and =mr list --search= narrow
338one repository. What someone types is quoted term by term, so an FTS5
339operator — =c++=, =AND=, a lone quote — is a word to match and never a
340syntax error. =repo grep= remains the per-repository file-contents
341search.
342
343A saved query is a named query over issues and merge requests across
344every repository the caller can read (#292): =query save <name>
345<query>= (=--force= replaces), =query list=, =query show= with its
346count, =query run= for the rows, =query remove=, =query pin= and
347=unpin=. =issue list --query <name>= and =mr list --query <name>= run
348one narrowed to their kind, and =--q '<query>'= takes one written out.
349Results are newest first, always paged with ={items, next}= and fifty
350rows by default, each naming its repository. Readability is the
351search rule, decided in the SQL, so a private repository someone else
352owns is neither a row nor part of a count. =dashboard= carries each
353pinned query's count and first five rows under =queries=; the web
354shows them on the dashboard and serves =/<owner>/-/queries= and
355=/<owner>/-/queries/<name>=, which are a 404 under anyone else's name.
356Saving, removing and pinning have no web form yet.
357
358The about text is =profile/README.{md,org,markdown}= on the default
359branch of =<owner>/.gitbay=, resolved in that order, so the extension
360picks the renderer rather than a stored format. =profile show= reports
361it as =about=, =about_format= and =about_path=. It reads with the
362repository's own access, so a private =.gitbay= is a profile with no
363about text to anyone but its owner and the admins. A repository whose
364name starts with a dot stays out of =explore= and off the profile's
365repository list. On the web a profile is tabs: =/<owner>= is About —
366the text, the year of squares and a log of the newest thirty events —
367then =/<owner>/-/repositories=, =/<owner>/-/bookmarks=,
368=/<owner>/-/snippets=, and =/<owner>/-/people= for an organization's
369members and teams. A tab nobody may open is not offered and its URL is
370a 404: bookmarks are the viewer's own, only a user has snippets, and
371people is the org admin panel. The log counts what the graph over it
372counts — a user's own events, an organization's repositories' — on
373public repositories only; =activity.atom= is the feed that goes back
374further. The CLI's =profile show= is unchanged and still returns all of
375it at once. The iOS client decodes and renders both formats,
376through the same OrgSwift path a README takes.
377
378=help= lists the command registry. Bare it is an index, one line per
379command, sorted. With a prefix (=help mr=) it adds each command's
380argument syntax, which is the only place flags are written down;
381=gitbay <cmd> --help= asks the server for the same thing, and =--json=
382returns ={path, summary, usage}=. No web page renders it, and a native
383client has no use for one (krz/gitbay#57).
384
385* Accounts
386
387| capability                  | cli | web | ios |
388|-----------------------------+-----+-----+-----|
389| SSH keys: list, add, remove | yes | yes | yes |
390| SSH key label               | yes | yes | yes |
391| SSH key expiry and last use | yes | no  | no  |
392| PGP keys: list, add, remove | yes | yes | yes |
393| email add and verify        | yes | yes | yes |
394| email list, remove, primary | yes | yes | yes |
395| dashboard aggregate         | yes | yes | yes |
396| notification inbox          | yes | yes | yes |
397| activity mail on, off       | yes | yes | yes |
398| reply by mail on, off       | yes | yes | no  |
399| watch writable repos        | yes | yes | yes |
400| push device add             | yes | yes | yes |
401| push device list            | yes | yes | yes |
402| push device remove          | yes | yes | yes |
403| activity push on, off       | yes | yes | yes |
404| web colour scheme           | yes | yes | n/a |
405| web diff layout             | yes | yes | n/a |
406| API token mint              | yes | yes | no  |
407| API token list, revoke      | yes | yes | no  |
408| API token revoke with what it created | yes | no  | no  |
409| account export bundle       | yes | yes | n/a |
410| profile set                 | yes | yes | yes |
411| write the profile about     | yes | yes | yes |
412| request a login link        | n/a | yes | n/a |
413| account import bundle       | yes | no  | n/a |
414
415Notifications land in an inbox row per recipient whether or not the
416instance sends mail, and mail is the second half when SMTP is
417configured. =notifications list= reads it, unread by default;
418=notifications read <id>... | --all= clears it; the dashboard and the
419web rail carry the unread count. =repo watch= adds you to a
420repository's notifications, =repo mute= silences it, and =repo unwatch=
421returns you to the default from either — told about work you are part
422of, nothing more. =notifications settings watch on= widens that default
423to every repository you can write to, without a row per repository. A
424mute wins over owning the repository, having written the thread, or the
425preference.
426
427Push is the third leg beside inbox and mail, delivered to Apple devices
428an account has registered. =notifications device add= runs on every
429surface like every other command, but no web page offers a form for
430it, because only the iOS app can produce an APNs device token — a
431browser has no way to ask Apple for one. =device list= and =device
432remove= have no such limit and are yes on the web like the rest.
433
434Replying to issue and merge request mail posts a comment (#295) when
435the instance reads a reply mailbox (=[mail.inbound]=) and the account
436ran =notifications settings reply on=. The account page shows the
437switch only on such an instance. The reply is itself a fourth surface
438for =issue comment= and =mr comment= and nothing else: it is dispatched
439as that command, so it cannot do what the command would refuse.
440=admin mail inbound check= has no page, like the rest of instance
441administration.
442
443A login link is requested from the login page by username or verified
444address, and arrives by mail: it works once and expires in fifteen
445minutes. The row is =n/a= for the CLI because a terminal with a
446registered key runs =web login=, which mints a link directly and needs
447no mail. It exists because an account with no SSH key had no way into
448the web at all (krz/gitbay#155). The page offers the form only when the
449instance has SMTP configured; there is no separate switch. The response
450never says whether the account exists. It is =n/a= on iOS for the same
451reason it is on the CLI, from the other end: the app authenticates with
452a bearer token pasted at sign-in, so a one-time link into the web
453unlocks nothing it can use.
454
455The account export bundle is =n/a= on iOS on the archive-download
456argument above — a JSON bundle has nowhere useful to land on a phone,
457and the web route stays the way to get one.
458
459=profile set= carries description, website and links; the JSON API runs
460it like any other write. The account settings page has the form, and so
461does the iOS client: =--link= replaces the whole set rather than
462appending, so a client sends every link it keeps on every save, and
463=--link ''= is how they are cleared.
464
465The about text is not among those flags. It is a file, written by a push
466or =repo commit-file= like any other file, which is why writing it is
467yes on every surface: anything that can commit a file can write it. The
468settings page points at the file and offers to create =<owner>/.gitbay=
469when there is none.
470
471* Administration
472
473| capability                      | cli | web | ios |
474|---------------------------------+-----+-----+-----|
475| account list, filter by state   | yes | yes | no  |
476| account show                    | yes | no  | no  |
477| promote, demote                 | yes | yes | no  |
478| disable, enable                 | yes | yes | no  |
479| account create, delete          | yes | no  | no  |
480| invite                          | yes | no  | no  |
481| worker queues                   | yes | yes | no  |
482| runners                         | yes | no  | no  |
483| repository list, archive, visibility | yes | no | no |
484| rebuild a symbol index          | yes | no  | no  |
485| audit log                       | yes | no  | no  |
486| instance statistics             | yes | no  | no  |
487| inbound mail check              | yes | no  | no  |
488
489=/admin/users= carries the account list with the command's state
490filter and cursor, and promote, demote, disable and enable per row;
491demote and disable ask for the username to be typed. The rest is a
492page nobody has built yet rather than a refusal — see below. Account
493creation and deletion stay on the command line on purpose: one takes a
494key, the other cannot be undone.
495
496* Organizations
497
498| capability                | cli | web | ios |
499|---------------------------+-----+-----+-----|
500| read members and teams    | yes | yes | yes |
501| members add, remove, role | yes | yes | yes |
502| teams create, delete      | yes | yes | yes |
503| team members              | yes | yes | yes |
504| team repo grants          | yes | yes | yes |
505| create, rename            | yes | yes | yes |
506| delete                    | yes | n/a | n/a |
507| profile                   | yes | no  | yes |
508
509* Pagination
510
511=issue list=, =mr list=, =repo list=, =feed=, =build list= and =repo
512symbols= take
513=--limit <n>= and =--cursor <c>=. Cursors are opaque; each page carries
514the next one. Without the flags a list stays as it was, so existing
515scripts are unchanged — for =build list= that means the newest fifty
516matching builds, which is what the cursor now reaches past. The web
517pages the issue and merge request lists at fifty and the builds list at
518thirty with the same cursors; iOS pages with them too.
519
520* CLI only, for now
521
522Build secrets, mirror configuration and tokens, custom domain claims,
523web session listing and revocation, deploy keys, and instance
524administration have no page yet. Until #234 these were
525refused outright on the other surfaces; the refusal is gone, so each is
526now a page waiting to be built rather than a rule. A credential still
527travels on stdin wherever it is set, since argv is world-readable in
528/proc and the audit log keeps flag values.
529
530Applying a suggestion on a repository that requires signed commits is
531CLI-only by mechanism: the server has no key to sign the commit with,
532so =gitbay mr apply-suggestion= makes and signs it in a clone with the
533user's own git signing configuration and pushes it. The web shows that
534command in place of the button.
535
536Deleting an organization and pruning merge request heads (=admin mr
537prune=) stay CLI-only for now. Deleting or transferring a repository is a
538settings section on the web and asks for the repository's path to be
539typed first.
540
541=n/a= means a surface cannot usefully carry the capability at all —
542see the archive note above.