mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-26 20:00:08 +00:00
865d792874
* feat(pricing): collapse to two tiers (Community + Admiral) Collapse Sencho's pricing from three tiers (Community / Skipper / Admiral) to two: a generous free Community tier and a single paid Admiral tier. The Skipper tier is removed. Now free in Community: auto-heal, auto-update, scheduled operations, webhooks, notification routing, Fleet Actions and bulk operations, SSO preset providers (Google / GitHub / Okta), unlimited users with admin and viewer roles, and deploy safety (atomic deploys, auto-rollback, and one-click rollback). Admiral (paid) is focused on running and governing a fleet: blueprints, Fleet Secrets, deploy enforcement, vulnerability report export, audit log, host console, private registries, mesh networking, node cordon, managed cloud backup, LDAP / Active Directory SSO, and the advanced RBAC roles (deployer, node-admin, auditor) with per-resource scoped assignments. Internally the license variant distinction is removed so tier is binary (community / paid). License validation still verifies the Lemon Squeezy store and product before granting paid status. Docs and the contributor guide are updated to the two-tier model. * docs(pricing): correct licensing page to two-tier pricing and tidy stale tier wording The licensing docs page kept the old Admiral pricing plus a Founder Lifetime column and an Enterprise paragraph after the two-tier collapse. Update it to $12/month or $99/year, drop the lifetime and Enterprise content, and link to the pricing page for current pricing. Also fix stale "Skipper" wording in CLA.md, SUPPORT.md, one test title, and three test comments. Historical CHANGELOG entries and the retired-Skipper license-guard test are intentionally left as-is. * docs: align licensing and SSO pages with the two-tier model Correct the SSO overview so the Google, GitHub, and Okta presets read as available on every tier, matching the provider table; only LDAP and Active Directory require Sencho Admiral. Remove the lifetime-plan references from the licensing, settings, and troubleshooting pages so they reflect subscription-only Admiral pricing. * fix(rbac): omit scoped permissions from /me on the Community tier Scoped role assignments only take effect on the paid tier, but GET /api/permissions/me returned them unconditionally, so a downgraded instance with leftover assignments rendered per-resource affordances the API then rejected with 403. The endpoint now mirrors the permission middleware and includes scoped permissions only on the paid tier. Adds a regression test covering the downgrade case. * docs: use custom-pricing wording on the contact page The two-tier model has no Enterprise tier; reword the contact page's enterprise pricing/deals to custom pricing/deals so it does not imply a tier that no longer exists.
204 lines
6.4 KiB
Plaintext
204 lines
6.4 KiB
Plaintext
---
|
|
title: API Overview
|
|
description: Authenticate, route requests to nodes, and integrate Sencho into your CI/CD pipelines.
|
|
---
|
|
|
|
Sencho exposes a REST API for automating stack deployments, managing webhooks, monitoring fleet health, and integrating with CI/CD pipelines. Since Sencho is self-hosted, the API base URL is your own instance.
|
|
|
|
## Base URL
|
|
|
|
```
|
|
https://your-sencho-instance:1852/api
|
|
```
|
|
|
|
Replace with your actual Sencho host and port. All API paths are prefixed with `/api`.
|
|
|
|
## Authentication
|
|
|
|
Authenticated endpoints require a **Bearer token** in the `Authorization` header. Generate API tokens from **Settings > API Tokens** in the Sencho dashboard.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
|
|
https://your-sencho-instance:1852/api/stacks
|
|
```
|
|
|
|
API tokens are 56-character opaque strings that begin with `sen_sk_`, for example `sen_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`. The prefix makes them easy to identify in logs and is recognized by secret-scanning tools (GitHub, TruffleHog, GitGuardian).
|
|
|
|
### Token scopes
|
|
|
|
Every token is created with one of three permission levels:
|
|
|
|
| Scope | Allowed actions |
|
|
|-------|----------------|
|
|
| **Read Only** | `GET` requests only — view stacks, containers, and fleet status |
|
|
| **Deploy Only** | Everything in Read Only, plus stack operations: deploy, down, restart, stop, start, update |
|
|
| **Full Admin** | Full stack, container, and node management — all read and write operations |
|
|
|
|
Regardless of scope, all API tokens are blocked from managing other tokens, users, licenses, and SSO configuration.
|
|
|
|
## Node routing
|
|
|
|
Sencho manages multiple nodes (local and remote). To target a specific node, include one of:
|
|
|
|
- **Header:** `x-node-id: 1`
|
|
- **Query parameter:** `?nodeId=1`
|
|
|
|
If omitted, the request targets the default node.
|
|
|
|
```bash
|
|
# Target node ID 2
|
|
curl -H "Authorization: Bearer TOKEN" \
|
|
-H "x-node-id: 2" \
|
|
https://your-sencho-instance:1852/api/stacks
|
|
```
|
|
|
|
## Error format
|
|
|
|
All error responses follow the same shape:
|
|
|
|
```json
|
|
{
|
|
"error": "Human-readable error message",
|
|
"code": "MACHINE_READABLE_CODE"
|
|
}
|
|
```
|
|
|
|
The `code` field is present for specific error types:
|
|
|
|
| Code | Meaning |
|
|
|------|---------|
|
|
| `PAID_REQUIRED` | Endpoint requires an Admiral license |
|
|
| `SCOPE_DENIED` | API token scope does not allow this operation |
|
|
|
|
## Input validation
|
|
|
|
All endpoints that accept a `stackName` path parameter validate it against the pattern `^[a-zA-Z0-9_-]+$`. Stack names may only contain **alphanumeric characters, hyphens, and underscores**. Requests with invalid stack names are rejected immediately:
|
|
|
|
```json
|
|
// 400 Bad Request
|
|
{
|
|
"error": "Invalid stack name"
|
|
}
|
|
```
|
|
|
|
This applies to all stack endpoints: read, write, deploy, down, restart, stop, start, update, rollback, backup, delete, and container listing.
|
|
|
|
## Rate limiting
|
|
|
|
Sencho uses a tiered rate limiting system that balances security with usability:
|
|
|
|
| Tier | Limit | Applies to | Keyed by |
|
|
|------|-------|------------|----------|
|
|
| **Polling** | 300/min | Dashboard status endpoints (`/stats`, `/system/stats`, `/stacks/statuses`, etc.) | User session or API token |
|
|
| **Standard** | 200/min | All other API endpoints | User session or API token |
|
|
| **Webhooks** | 500/min | `POST /webhooks/:id/trigger` | IP address |
|
|
| **Auth** | 5-10/15min | Login, setup, SSO endpoints | IP address |
|
|
|
|
Authenticated requests are rate-limited per credential (per user session, or per API token). This prevents teams behind shared NAT or VPN from pooling rate limit budgets, and lets two API-token-driven automations under the same account run on independent budgets. Unauthenticated requests fall back to IP-based limiting.
|
|
|
|
Internal node-to-node traffic (requests authenticated with node proxy tokens) bypasses rate limiting entirely.
|
|
|
|
When exceeded, the server responds with `429 Too Many Requests`:
|
|
|
|
```json
|
|
{
|
|
"error": "Too many requests. Please try again shortly."
|
|
}
|
|
```
|
|
|
|
Standard rate limit headers (`RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`) are included in all API responses, so clients can self-throttle accordingly.
|
|
|
|
The default limits can be tuned via environment variables (`API_RATE_LIMIT`, `API_POLLING_RATE_LIMIT`). See [Self-Hosting](/operations/self-hosting) for details.
|
|
|
|
## License tier requirements
|
|
|
|
Some endpoints are gated by license tier:
|
|
|
|
| Tier | Gated features |
|
|
|------|---------------|
|
|
| **Admiral** | Scan policies, Private registries |
|
|
|
|
Requests to gated endpoints on Community return `403` with the `PAID_REQUIRED` error code.
|
|
|
|
## WebSocket endpoints
|
|
|
|
Sencho also provides real-time streaming via WebSocket connections. These are not part of the OpenAPI spec (OpenAPI does not support WebSocket protocols) but are documented here for completeness.
|
|
|
|
### Stack log streaming
|
|
|
|
Stream live logs from a stack's containers.
|
|
|
|
**URL:** `wss://your-sencho-instance:1852/api/stacks/{stackName}/logs?nodeId={nodeId}`
|
|
|
|
**Authentication:** Pass the token as a cookie (`sencho_token`) or Bearer token. For WebSocket connections, authentication is verified during the upgrade handshake.
|
|
|
|
<CodeGroup>
|
|
|
|
```javascript Node.js
|
|
import WebSocket from "ws";
|
|
|
|
const ws = new WebSocket(
|
|
"wss://your-sencho-instance:1852/api/stacks/my-app/logs",
|
|
{ headers: { Cookie: "sencho_token=YOUR_JWT" } }
|
|
);
|
|
|
|
ws.on("message", (data) => {
|
|
console.log(data.toString());
|
|
});
|
|
```
|
|
|
|
```bash cURL (upgrade check)
|
|
curl -i -N \
|
|
-H "Connection: Upgrade" \
|
|
-H "Upgrade: websocket" \
|
|
-H "Cookie: sencho_token=YOUR_JWT" \
|
|
https://your-sencho-instance:1852/api/stacks/my-app/logs
|
|
```
|
|
|
|
</CodeGroup>
|
|
|
|
### Container exec
|
|
|
|
Open an interactive shell session inside a running container.
|
|
|
|
**URL:** `wss://your-sencho-instance:1852/ws`
|
|
|
|
**Authentication:** Cookie-based JWT only. API tokens with `read-only` or `deploy-only` scope are blocked.
|
|
|
|
<CodeGroup>
|
|
|
|
```javascript Node.js
|
|
import WebSocket from "ws";
|
|
|
|
const ws = new WebSocket("wss://your-sencho-instance:1852/ws", {
|
|
headers: { Cookie: "sencho_token=YOUR_JWT" },
|
|
});
|
|
|
|
ws.on("open", () => {
|
|
// Initiate exec session
|
|
ws.send(
|
|
JSON.stringify({
|
|
action: "execContainer",
|
|
containerId: "abc123...",
|
|
})
|
|
);
|
|
});
|
|
|
|
ws.on("message", (data) => {
|
|
// Terminal output
|
|
process.stdout.write(data.toString());
|
|
});
|
|
|
|
// Send terminal input
|
|
ws.send(JSON.stringify({ type: "input", data: "ls -la\n" }));
|
|
|
|
// Resize terminal
|
|
ws.send(JSON.stringify({ type: "resize", cols: 120, rows: 40 }));
|
|
```
|
|
|
|
</CodeGroup>
|
|
|
|
<Warning>
|
|
Container exec requires an **admin** role. API tokens with `read-only` or `deploy-only` scope are blocked, as are node proxy tokens.
|
|
</Warning>
|