API: a wiki says it takes no proposals, rather than 'no such repository' a0dd06b0094e
OWNER/NAME.wiki has no row of its own, so oh proposal create in a wiki checkout got 'HTTP 404: no such repository' though pushing to it works. For a reader of the repository the API now answers that it is a wiki, cloned and pushed with oxy, taking no proposals, issues or runs, and how to publish a bookmark: merge it into main and push main. Others still get 'no such repository'. refs #128
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-10-11 11:42 UTC
- Signature
- ✔ signed by Andy McCall
- Hash
a0dd06b0094eb52d4347f6bde0572de667a0d2cbac5878d9e6928ec3bba09947- Depends on
- 3f02e5ea4f2d 66fd9d6b1452 93be9ce4653e b64e2537d702 d23464c0ac60
- Depended on by
- nothing yet
- In bookmarks
- api-unknown-fields cancel-landed-runs clear-waiting close-proposal-140 diffusion-pin-bookmark draft-ready image-check main oh-comment-body-file proposal-list-fast wiki-says-so
- In tags
- v0.4.2 v0.5.0 v0.5.1 v0.5.2 v0.6.0 v0.6.1 v0.7.0 v0.8.0 v0.9.0 v0.9.1 v0.9.11 v0.9.15 v0.9.16 v0.9.19 v0.9.2 v0.9.20 v0.9.21 v0.9.22 v0.9.23 v0.9.24 v0.9.3 v0.9.4 v0.9.5 v0.9.6 v0.9.7 v0.9.8 v0.9.9
- Edits
- 4 atoms, 0 tree operations, 3 files
Browse the tree at this change
modified crates/hub/src/api/mod.rs +14 −0
| … | 333 unchanged lines |
||
| 334 | 334 | name: &str, |
|
| 335 | 335 | access: Access, |
|
| 336 | 336 | ) -> Result<(RepoName, db::repos::RepoRow, Role), ApiError> { |
|
| 337 | + | // A wiki (`NAME.wiki`) has no row of its own, so no proposals, issues |
|
| 338 | + | // or runs (oxygenhub#128): say so to those who may read it, rather than |
|
| 339 | + | // that it does not exist. |
|
| 340 | + | if let Some(base) = name.strip_suffix(".wiki") { |
|
| 341 | + | if let Some(row) = db::repos::get(&app.db, owner, base).await? { |
|
| 342 | + | let role = auth::roles::role_for(&app.db, c.account.as_ref(), &row).await?; |
|
| 343 | + | if auth::roles::allows(role, Access::Read) { |
|
| 344 | + | return Err(not_found(&format!( |
|
| 345 | + | "{owner}/{name} is the wiki of {owner}/{base}: it is cloned and pushed with oxy, and takes no proposals, \ |
|
| 346 | + | issues or runs; to publish a bookmark, merge it into main (oxy merge BOOKMARK on main) and push main" |
|
| 347 | + | ))); |
|
| 348 | + | } |
|
| 349 | + | } |
|
| 350 | + | } |
|
| 337 | 351 | let repo = RepoName::new(owner, name).ok_or_else(|| not_found("no such repository"))?; |
|
| 338 | 352 | let row = db::repos::get(&app.db, owner, name).await?.ok_or_else(|| not_found("no such repository"))?; |
|
| 339 | 353 | let role = auth::roles::role_for(&app.db, c.account.as_ref(), &row).await?; |
|
| … | 1824 unchanged lines |
modified crates/hub/tests/api.rs +10 −0
| … | 277 unchanged lines |
||
| 278 | 278 | assert_eq!(v["number"], 2); |
|
| 279 | 279 | let state = v["projected_state"].as_str().unwrap().to_string(); |
|
| 280 | 280 | assert_eq!(v["landable"], true); |
|
| 281 | + | // A wiki takes no proposals, and says so rather than "no such |
|
| 282 | + | // repository" (oxygenhub#128); a repository's that does not exist |
|
| 283 | + | // still does not. |
|
| 284 | + | let (st, v) = |
|
| 285 | + | api(app, "POST", "/api/v1/repos/andy/demo.wiki/proposals", Some(&bob_rw), Some(r#"{"title":"W","target":"main","source":"p"}"#)) |
|
| 286 | + | .await; |
|
| 287 | + | let detail = v["detail"].as_str().unwrap_or_default(); |
|
| 288 | + | assert!(st == StatusCode::NOT_FOUND && detail.contains("is the wiki of andy/demo") && detail.contains("push main"), "{v}"); |
|
| 289 | + | let (_, v) = api(app, "GET", "/api/v1/repos/andy/nope.wiki/proposals", Some(&bob_rw), None).await; |
|
| 290 | + | assert_eq!(v["detail"], "no such repository"); |
|
| 281 | 291 | // Its files, and each side's bytes, for editors' diff views. |
|
| 282 | 292 | let (st, v) = api(app, "GET", "/api/v1/repos/andy/demo/proposals/2/files", None, None).await; |
|
| 283 | 293 | assert_eq!(st, StatusCode::OK, "{v}"); |
|
| … | 1113 unchanged lines |
modified docs/spec.md +1 −1
| … | 331 unchanged lines |
||
| 332 | 332 | ||
| 333 | 333 | ### 6.11 Wiki (done 2026-10-04) |
|
| 334 | 334 | ||
| 335 | - | A repository may have a **wiki** (oxygenhub#104): Markdown pages kept as an Oxygen repository of their own under `<data>/wikis/<owner>/<name>`, with no row of its own; it follows the repository's visibility, roles, archiving, transfer and deletion. A page `Getting-Started` is the file `Getting-Started.md` at the root of bookmark `main`; `_Sidebar.md` is shown beside every page, and `Home` is the front page. On the web (`/{owner}/{name}/wiki`, `/wiki/{page}`, `/wiki/{page}/edit`, `/wiki/{page}/history`, `/wiki/_pages` with a search over titles and text, `/wiki/_raw/{path}` for images): readers read, writers create, edit, rename and delete pages, and every edit is a change authored by the user and signed by the hub as their delegate, exactly as a code edit (§6.9), so it needs the same delegation. Links between pages are relative (`[Other](Other)`). By client, the wiki is `oxy clone HUB/{owner}/{name}.wiki`: the wire protocol maps that name onto the wiki store with the repository's permissions, pushes need write access and not archived, start no run and ring no webhook; a repository can therefore not be named `*.wiki`. The Wiki tab shows when a wiki exists or the viewer may start one. Settings › Advanced › Delete wiki data moves the wiki to the trash. Audited as `wiki.edited`, `wiki.deleted`, `wiki.data_deleted`; webhooks get a `wiki` event. |
|
| 335 | + | A repository may have a **wiki** (oxygenhub#104): Markdown pages kept as an Oxygen repository of their own under `<data>/wikis/<owner>/<name>`, with no row of its own; it follows the repository's visibility, roles, archiving, transfer and deletion. A page `Getting-Started` is the file `Getting-Started.md` at the root of bookmark `main`; `_Sidebar.md` is shown beside every page, and `Home` is the front page. On the web (`/{owner}/{name}/wiki`, `/wiki/{page}`, `/wiki/{page}/edit`, `/wiki/{page}/history`, `/wiki/_pages` with a search over titles and text, `/wiki/_raw/{path}` for images): readers read, writers create, edit, rename and delete pages, and every edit is a change authored by the user and signed by the hub as their delegate, exactly as a code edit (§6.9), so it needs the same delegation. Links between pages are relative (`[Other](Other)`). By client, the wiki is `oxy clone HUB/{owner}/{name}.wiki`: the wire protocol maps that name onto the wiki store with the repository's permissions, pushes need write access and not archived, start no run and ring no webhook; a repository can therefore not be named `*.wiki`. A wiki takes no proposals, issues or runs: the API answers a reader asking for one under `OWNER/NAME.wiki` with a 404 that says so and how to publish a bookmark (merge it into `main` and push), not "no such repository" (#128). The Wiki tab shows when a wiki exists or the viewer may start one. Settings › Advanced › Delete wiki data moves the wiki to the trash. Audited as `wiki.edited`, `wiki.deleted`, `wiki.data_deleted`; webhooks get a `wiki` event. |
|
| 336 | 336 | ||
| 337 | 337 | ## 7. Proposals and review |
|
| 338 | 338 | ||
| … | 374 unchanged lines |