mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-28 12:49:03 +00:00
52b46753af
Ships the v1 MVP for the Federation tab as placement control, not
placement automation:
- Cordon a node: marks the node unschedulable so the BlueprintReconciler
skips it for new placements only. Existing deployments continue to
drift-check and redeploy on revision changes; cordon never triggers
withdraw or eviction. Toggle on the NodeCard kebab (Admiral, admin
role); Cordoned pill renders for all tiers.
- Pin a blueprint to a node: stores blueprints.pinned_node_id, replacing
the desired set with the pinned node regardless of selector. Pin
overrides cordon by design. Action lives only in the Federation tab;
BlueprintDetail and the deployment table show read-only Pinned
indicators.
Backend: idempotent migrations add nodes.cordoned/cordoned_at/cordoned_reason
and blueprints.pinned_node_id. New routes POST /api/nodes/:id/cordon,
POST /api/nodes/:id/uncordon, PUT /api/blueprints/:id/pin, all gated by
requireAdmiral plus requireAdmin. Audit summaries added so the existing
auditLog middleware records every operator action. deleteNode clears
dangling pins.
Reconciler: pin override evaluated before selector match; cordon filter
applied only to the new-placement branch (deploy/stateReview without an
existing deployment). 11 new Vitest cases cover cordon filter, pin
override, pin-overrides-cordon, missing pin target, pin shrinks
desired set (stateless withdraw + stateful evict_blocked), and pin
clearing on node delete.
Frontend: new FederationTab.tsx with cordoned-nodes summary and
pin-policy table. Federation moved out of the experimental flag into
{isAdmiral && (...)} + AdmiralGate, mirroring the Routing tab pattern.
Secrets stays under experimental.
Tests pass: backend tsc, full Vitest suite (1704 passed), frontend
tsc -b, ESLint (0 errors). Manual verification via the local dev
instance confirmed the tab is hidden at Community, the kebab and pill
render at Admiral, and cordon and pin endpoints round-trip end to end.
Refs cut-line-1.0.md Federation v1 MVP.
325 lines
9.7 KiB
JSON
325 lines
9.7 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 & Deployments",
|
|
"pages": [
|
|
"features/stack-management",
|
|
"features/stack-activity",
|
|
"features/editor",
|
|
"features/stack-file-explorer",
|
|
"features/deploy-progress",
|
|
"features/resources",
|
|
"features/app-store",
|
|
"features/atomic-deployments",
|
|
"features/deploy-enforcement",
|
|
"features/blueprint-model",
|
|
"features/git-sources",
|
|
"features/stack-labels"
|
|
]
|
|
},
|
|
{
|
|
"group": "Observability",
|
|
"pages": [
|
|
"features/dashboard",
|
|
"features/global-search",
|
|
"features/global-observability",
|
|
"features/alerts-notifications",
|
|
"features/notification-routing",
|
|
"features/audit-log"
|
|
]
|
|
},
|
|
{
|
|
"group": "Fleet & Multi-Node",
|
|
"pages": [
|
|
"features/multi-node",
|
|
"features/pilot-agent",
|
|
"features/sencho-mesh",
|
|
"features/fleet-view",
|
|
"features/fleet-federation",
|
|
"features/fleet-actions",
|
|
"features/fleet-sync",
|
|
"features/fleet-backups",
|
|
"features/remote-updates",
|
|
"features/scheduled-operations"
|
|
]
|
|
},
|
|
{
|
|
"group": "Security & Identity",
|
|
"pages": [
|
|
"features/two-factor-authentication",
|
|
"features/rbac",
|
|
"features/sso",
|
|
"features/api-tokens",
|
|
"features/vulnerability-scanning",
|
|
"features/cve-suppressions",
|
|
"features/private-registries"
|
|
]
|
|
},
|
|
{
|
|
"group": "Automation",
|
|
"pages": [
|
|
"features/auto-update-policies",
|
|
"features/auto-heal-policies",
|
|
"features/webhooks"
|
|
]
|
|
},
|
|
{
|
|
"group": "Platform",
|
|
"pages": [
|
|
"features/sidebar",
|
|
"features/host-console"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"group": "Reference",
|
|
"pages": [
|
|
"reference/settings",
|
|
"features/licensing",
|
|
"features/node-compatibility",
|
|
"security",
|
|
"reference/security-advisories",
|
|
"reference/contact"
|
|
]
|
|
},
|
|
{
|
|
"group": "Operations",
|
|
"pages": [
|
|
"operations/self-hosting",
|
|
"operations/upgrade",
|
|
"operations/backup",
|
|
"operations/troubleshooting",
|
|
"operations/verifying-images",
|
|
"operations/trivy-setup",
|
|
"operations/two-factor-admin"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"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"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|