chore: v2.8.15 — Oh My Pi login sharing, omp --allow-home, Markdown Preview default, first-login password

- omp-share.js: an admin's switch (S3) runs omp's own auth broker + gateway as
  the host on loopback; a member's omp pane reaches it as a scoped client keyed
  by its pane token (clients file = live omp panes only), runs on
  --model agenthub/<model>, never holds a credential.
- omp catalog: --allow-home, so a workspace at the account's home keeps its
  sessions there (they were recorded under a temp dir and dropped).
- Settings → Appearance → Open Markdown as: Preview (default) or Raw, for
  Files/Changes, the config viewer and a chat's file panel.
- First-login password change and password rules, avatar URLs, Artifacts
  "Mine" includes installed shared skills/plugins, a member's own hook pages.
This commit is contained in:
2026-10-22 10:04:30 +07:00
parent 8a6dc6a29e
commit 750d74a2af
66 changed files with 3021 additions and 696 deletions
+31 -2
View File
@@ -14,6 +14,7 @@
* - GET/PATCH /api/me/account, POST /api/me/password, POST /api/me/sign-out-others
* (Auth) — Settings → Account: the account's own profile, password and logins
* - GET/PUT/DELETE /api/me/avatar (Auth) — the account's own picture
* - POST /api/me/avatar/url (Auth) — the same picture downloaded from a link
* - GET/PATCH /api/users/{id} (Auth) — the Users page's Edit user form
* - GET /api/users/{id}/avatar (Auth) — one account's picture (admin/analyst)
* - GET /api/users/tmux, POST /api/users/{id}/tmux-restart, POST /api/users/tmux-restart-idle
@@ -267,7 +268,7 @@ const paths = {
tags: ["Auth"],
operationId: "changeMyPassword",
summary:
"Change the account's own password: the current one required (throttled); this login stays, every other ends",
"Change the account's own password: the current one required (throttled); the new one must pass every rule (8+ characters, lower, upper, digit, symbol, not the username) and differ from the current one; this login stays, every other ends; clears mustChangePassword",
requestBody: {
required: true,
content: {
@@ -285,7 +286,7 @@ const paths = {
},
responses: {
200: { description: "Changed ({ok: true})" },
400: err("EBADPASSWORD"),
400: err("EBADPASSWORD / EWEAKPASSWORD (error.rules names the failed rules)"),
401: err("EAUTH — no login cookie (a pane token is refused)"),
403: err("EREAUTH (current password wrong) / ELOCALMODE"),
429: err("ETOOMANY — 10 wrong passwords in 15 minutes"),
@@ -494,6 +495,34 @@ const paths = {
},
},
},
"/api/me/avatar/url": {
post: {
tags: ["Auth"],
operationId: "setMyAvatarFromUrl",
summary:
"Set the account's picture from an https link the server downloads (public addresses only, at most 3 redirects, PNG/JPEG/GIF/WebP, at most 1 MB). Login cookie only, audited",
requestBody: {
required: true,
content: {
"application/json": {
schema: {
type: "object",
required: ["url"],
properties: { url: { type: "string", format: "uri" } },
},
},
},
},
responses: {
200: { description: "Set", content: accountBody },
400: err("EBADURL / EPRIVATEURL / EBADIMAGE"),
401: err("EAUTH — no login cookie (a pane token is refused)"),
403: err("ELOCALMODE"),
413: err("ETOOBIG"),
502: err("EFETCH — the link could not be downloaded"),
},
},
},
"/api/users/{id}/avatar": {
get: {
tags: ["Auth"],