Files
sencho/docs/docs.json
T
Anso c6d1631afe feat(recovery): add safe-mode recovery surface and emergency CLI (#1286)
* feat(recovery): add safe-mode recovery surface and emergency CLI

Add a read-only Recovery tab under Settings (admin-only) backed by a new
GET /api/diagnostics endpoint reporting app version, database integrity,
encryption-key status, Docker reachability, account and SSO counts, and
non-secret configuration. The endpoint loads without Docker or live metrics
so it stays available when the dashboard does not, requires a genuine admin
session, and builds its config block from a non-secret allowlist so no
credentials are ever exposed.

Expand the emergency command-line toolkit beyond the two-factor reset with
seven host-level commands: reset-password, create-emergency-admin,
clear-sessions, disable-sso, diagnostics, validate-db, and backup-data. Each
prints its result, exits with a meaningful status code, and writes an audit
entry where it changes state.

Document the toolkit in a new operator guide and link it from the recovery
and two-factor pages.

* feat(recovery): download the emergency command reference as a text file

The recovery commands are needed exactly when the dashboard is unreachable,
so reading them only in-app is a chicken-and-egg problem. Add a Download
button to the command-line section that saves the full
`docker compose exec sencho ...` reference as a text file, letting operators
keep it on hand before they need it. Reuses a shared download helper with the
existing diagnostics export.

* fix(recovery): harden diagnostics, backup, and emergency-admin against edge cases

Address findings from an independent review of the recovery toolkit:

- DiagnosticsService now degrades instead of throwing when a queried table is
  missing or corrupt: each read falls back and is folded into database.ok, so a
  broken database reports "problem detected" rather than failing the whole
  endpoint or showing a misleading healthy state with zeroed counts.
- backup-data refuses a destination that resolves to the live database, which
  would otherwise report success while producing no separate copy.
- create-emergency-admin now applies the same username rule as the user-
  management route, extracted to a shared helper so both stay in sync.

Adds tests for a missing read table, a malformed emergency-admin username, and
the backup same-target rejection.
2026-06-02 16:11:24 -04:00

332 lines
9.9 KiB
JSON

{
"$schema": "https://mintlify.com/docs.json",
"theme": "mint",
"name": "Sencho",
"colors": {
"primary": "#00BEC7",
"light": "#007982",
"dark": "#00BEC7"
},
"logo": {
"light": "/images/logo/logo-light.png",
"dark": "/images/logo/logo-dark.png",
"href": "https://sencho.io"
},
"favicon": "/images/logo/favicon.ico",
"appearance": {
"default": "dark"
},
"fonts": {
"family": "Geist"
},
"background": {
"decoration": "gradient",
"color": {
"dark": "#090909"
}
},
"navbar": {
"links": [
{
"type": "github",
"href": "https://github.com/studio-saelix/sencho"
}
],
"primary": {
"type": "button",
"label": "Get Started",
"href": "https://sencho.io/#pricing"
}
},
"footer": {
"socials": {
"github": "https://github.com/studio-saelix/sencho"
},
"links": [
{
"header": "Product",
"items": [
{ "label": "Website", "href": "https://sencho.io" },
{ "label": "Pricing", "href": "https://sencho.io/#pricing" },
{ "label": "Changelog", "href": "https://github.com/studio-saelix/sencho/releases" }
]
},
{
"header": "Community",
"items": [
{ "label": "GitHub", "href": "https://github.com/studio-saelix/sencho" },
{ "label": "Contributing", "href": "https://github.com/studio-saelix/sencho/blob/main/CONTRIBUTING.md" }
]
},
{
"header": "Legal",
"items": [
{ "label": "Terms of Service", "href": "https://sencho.io/terms" },
{ "label": "Privacy Policy", "href": "https://sencho.io/privacy" }
]
}
]
},
"api": {
"auth": {
"method": "bearer",
"name": "Authorization"
},
"playground": {
"display": "simple"
}
},
"navigation": {
"tabs": [
{
"tab": "Documentation",
"groups": [
{
"group": "Getting Started",
"pages": [
"getting-started/introduction",
"getting-started/quickstart",
"getting-started/configuration",
"getting-started/sso-quickstart"
]
},
{
"group": "Features",
"pages": [
"features/overview",
{
"group": "Stacks",
"expanded": true,
"pages": [
"features/stack-management",
"features/editor",
"features/stack-file-explorer",
"features/stack-activity",
"features/stack-labels",
"features/sidebar"
]
},
{
"group": "Deployment",
"expanded": true,
"pages": [
"features/deploy-progress",
"features/atomic-deployments",
"features/deploy-enforcement",
"features/git-sources",
"features/app-store",
"features/blueprint-model"
]
},
"features/resources",
{
"group": "Observability",
"expanded": true,
"pages": [
"features/dashboard",
"features/global-search",
"features/global-observability",
"features/alerts-notifications",
"features/audit-log"
]
},
{
"group": "Fleet",
"expanded": true,
"pages": [
"features/multi-node",
"features/pilot-agent",
"features/sencho-mesh",
"features/fleet-view",
"features/fleet-federation",
"features/fleet-actions",
"features/fleet-sync",
"features/fleet-secrets",
"features/fleet-backups",
"features/remote-updates",
"features/node-compatibility",
"features/host-console"
]
},
{
"group": "Automation",
"expanded": true,
"pages": [
"features/scheduled-operations",
"features/auto-update-policies",
"features/auto-heal-policies",
"features/webhooks"
]
},
{
"group": "Security & Identity",
"expanded": true,
"pages": [
"features/two-factor-authentication",
"features/rbac",
"features/sso",
"features/api-tokens",
"features/vulnerability-scanning",
"features/cve-suppressions",
"features/private-registries"
]
}
]
},
{
"group": "Operations",
"pages": [
"operations/self-hosting",
"operations/upgrade",
"operations/backup",
"operations/recovery",
"operations/emergency-cli",
"operations/troubleshooting",
"operations/verifying-images",
"operations/trivy-setup",
"operations/two-factor-admin"
]
},
{
"group": "Reference",
"pages": [
"reference/settings",
"features/licensing",
"reference/security",
"reference/contact"
]
}
]
},
{
"tab": "API Reference",
"openapi": "openapi.yaml",
"pages": [
"api-reference/overview",
"api-reference/security",
{
"group": "Health & Meta",
"pages": [
"GET /api/health",
"GET /api/meta",
"POST /api/system/update"
]
},
{
"group": "Stacks",
"pages": [
"GET /api/stacks",
"POST /api/stacks",
"GET /api/stacks/{stackName}",
"PUT /api/stacks/{stackName}",
"DELETE /api/stacks/{stackName}",
"GET /api/stacks/{stackName}/envs",
"GET /api/stacks/{stackName}/env",
"PUT /api/stacks/{stackName}/env",
"GET /api/stacks/{stackName}/containers",
"GET /api/stacks/{stackName}/services",
"POST /api/stacks/{stackName}/deploy",
"POST /api/stacks/{stackName}/down",
"POST /api/stacks/{stackName}/start",
"POST /api/stacks/{stackName}/stop",
"POST /api/stacks/{stackName}/restart",
"POST /api/stacks/{stackName}/update",
"POST /api/stacks/{stackName}/rollback",
"GET /api/stacks/{stackName}/backup"
]
},
{
"group": "Containers",
"pages": [
"GET /api/containers",
"GET /api/containers/{id}/logs",
"POST /api/containers/{id}/start",
"POST /api/containers/{id}/stop",
"POST /api/containers/{id}/restart"
]
},
{
"group": "API Tokens",
"pages": [
"POST /api/api-tokens",
"GET /api/api-tokens",
"DELETE /api/api-tokens/{id}"
]
},
{
"group": "Webhooks",
"pages": [
"GET /api/webhooks",
"POST /api/webhooks",
"PUT /api/webhooks/{id}",
"DELETE /api/webhooks/{id}",
"GET /api/webhooks/{id}/history",
"POST /api/webhooks/{id}/trigger"
]
},
{
"group": "Nodes",
"pages": [
"GET /api/nodes",
"POST /api/nodes",
"GET /api/nodes/{id}",
"PUT /api/nodes/{id}",
"DELETE /api/nodes/{id}",
"POST /api/nodes/{id}/test",
"GET /api/nodes/{id}/meta"
]
},
{
"group": "Fleet",
"pages": [
"GET /api/fleet/overview",
"GET /api/fleet/node/{nodeId}/stacks",
"GET /api/fleet/node/{nodeId}/stacks/{stackName}/containers",
"GET /api/fleet/update-status",
"POST /api/fleet/nodes/{nodeId}/update",
"POST /api/fleet/update-all",
"POST /api/fleet/snapshots",
"GET /api/fleet/snapshots",
"GET /api/fleet/snapshots/{id}",
"POST /api/fleet/snapshots/{id}/restore",
"DELETE /api/fleet/snapshots/{id}"
]
},
{
"group": "Scheduled Tasks",
"pages": [
"GET /api/scheduled-tasks",
"POST /api/scheduled-tasks",
"GET /api/scheduled-tasks/{id}",
"PUT /api/scheduled-tasks/{id}",
"DELETE /api/scheduled-tasks/{id}",
"PATCH /api/scheduled-tasks/{id}/toggle",
"POST /api/scheduled-tasks/{id}/run",
"GET /api/scheduled-tasks/{id}/runs",
"GET /api/scheduled-tasks/{id}/runs/export"
]
},
{
"group": "Registries",
"pages": [
"GET /api/registries",
"POST /api/registries",
"PUT /api/registries/{id}",
"DELETE /api/registries/{id}",
"POST /api/registries/{id}/test"
]
},
{
"group": "Image Updates",
"pages": [
"GET /api/image-updates",
"POST /api/image-updates/refresh",
"GET /api/image-updates/status"
]
}
]
}
]
}
}