@lamalibre/create-lamaste 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +118 -0
- package/README.md +114 -0
- package/bin/create-lamaste.js +15 -0
- package/package.json +54 -0
- package/scripts/bundle-vendor.js +110 -0
- package/scripts/lamaste-cert-info +62 -0
- package/scripts/lamaste-certbot +96 -0
- package/scripts/lamaste-priv +693 -0
- package/src/index.js +646 -0
- package/src/lib/accounts.js +86 -0
- package/src/lib/binaries.js +137 -0
- package/src/lib/cert-help-page.js +160 -0
- package/src/lib/env.js +132 -0
- package/src/lib/http-redirect.js +38 -0
- package/src/lib/ownership.js +231 -0
- package/src/lib/relay-services.js +103 -0
- package/src/lib/secrets.js +19 -0
- package/src/lib/service-config.js +311 -0
- package/src/lib/summary.js +131 -0
- package/src/lib/wrappers.js +63 -0
- package/src/tasks/gatekeeper.js +233 -0
- package/src/tasks/harden.js +293 -0
- package/src/tasks/mtls.js +193 -0
- package/src/tasks/nginx.js +265 -0
- package/src/tasks/node.js +110 -0
- package/src/tasks/panel.js +408 -0
- package/src/tasks/redeploy.js +438 -0
- package/vendor/docs/00-introduction/how-it-works.md +447 -0
- package/vendor/docs/00-introduction/quickstart.md +472 -0
- package/vendor/docs/00-introduction/what-is-lamaste.md +112 -0
- package/vendor/docs/01-concepts/authentication.md +464 -0
- package/vendor/docs/01-concepts/authorization.md +242 -0
- package/vendor/docs/01-concepts/certificates.md +452 -0
- package/vendor/docs/01-concepts/dns-and-domains.md +343 -0
- package/vendor/docs/01-concepts/mtls.md +490 -0
- package/vendor/docs/01-concepts/nginx-reverse-proxy.md +540 -0
- package/vendor/docs/01-concepts/security-model.md +600 -0
- package/vendor/docs/01-concepts/tickets.md +414 -0
- package/vendor/docs/01-concepts/tunneling.md +367 -0
- package/vendor/docs/02-guides/agent-setup.md +194 -0
- package/vendor/docs/02-guides/certificate-management.md +341 -0
- package/vendor/docs/02-guides/cloud-provisioning.md +406 -0
- package/vendor/docs/02-guides/desktop-app-setup.md +226 -0
- package/vendor/docs/02-guides/disaster-recovery.md +464 -0
- package/vendor/docs/02-guides/first-tunnel.md +230 -0
- package/vendor/docs/02-guides/installation.md +393 -0
- package/vendor/docs/02-guides/managing-users.md +255 -0
- package/vendor/docs/02-guides/onboarding.md +244 -0
- package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +375 -0
- package/vendor/docs/02-guides/static-sites.md +364 -0
- package/vendor/docs/03-architecture/e2e-three-vm-sequences.md +457 -0
- package/vendor/docs/03-architecture/installer-flow.md +151 -0
- package/vendor/docs/03-architecture/installer.md +445 -0
- package/vendor/docs/03-architecture/management-flow.md +288 -0
- package/vendor/docs/03-architecture/nginx-configuration.md +830 -0
- package/vendor/docs/03-architecture/onboarding-flow.md +164 -0
- package/vendor/docs/03-architecture/overview.md +541 -0
- package/vendor/docs/03-architecture/panel-client.md +416 -0
- package/vendor/docs/03-architecture/panel-server.md +695 -0
- package/vendor/docs/03-architecture/state-management.md +529 -0
- package/vendor/docs/03-architecture/system-overview.md +167 -0
- package/vendor/docs/04-api-reference/certificates.md +1141 -0
- package/vendor/docs/04-api-reference/gatekeeper.md +592 -0
- package/vendor/docs/04-api-reference/onboarding.md +473 -0
- package/vendor/docs/04-api-reference/overview.md +404 -0
- package/vendor/docs/04-api-reference/services.md +267 -0
- package/vendor/docs/04-api-reference/settings.md +343 -0
- package/vendor/docs/04-api-reference/sites.md +716 -0
- package/vendor/docs/04-api-reference/system.md +268 -0
- package/vendor/docs/04-api-reference/tickets.md +618 -0
- package/vendor/docs/04-api-reference/tunnels.md +417 -0
- package/vendor/docs/04-api-reference/users.md +333 -0
- package/vendor/docs/05-operations/backup-and-restore.md +342 -0
- package/vendor/docs/05-operations/monitoring.md +285 -0
- package/vendor/docs/05-operations/uninstalling.md +344 -0
- package/vendor/docs/05-operations/upgrades.md +270 -0
- package/vendor/docs/06-reference/config-files.md +1080 -0
- package/vendor/docs/06-reference/glossary.md +528 -0
- package/vendor/docs/06-reference/installer-flags.md +260 -0
- package/vendor/docs/06-reference/ports-and-services.md +244 -0
- package/vendor/docs/06-reference/troubleshooting.md +665 -0
- package/vendor/docs/_index.json +233 -0
- package/vendor/docs/gatekeeper-design.md +953 -0
- package/vendor/docs/package.json +15 -0
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +641 -0
- package/vendor/gatekeeper/dist/boot.d.ts +1 -0
- package/vendor/gatekeeper/dist/boot.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/boot.js +17 -0
- package/vendor/gatekeeper/dist/boot.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/access.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/access.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/access.js +33 -0
- package/vendor/gatekeeper/dist/cli/commands/access.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.js +110 -0
- package/vendor/gatekeeper/dist/cli/commands/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.d.ts +2 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.js +98 -0
- package/vendor/gatekeeper/dist/cli/commands/groups.js.map +1 -0
- package/vendor/gatekeeper/dist/cli/index.d.ts +3 -0
- package/vendor/gatekeeper/dist/cli/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/cli/index.js +45 -0
- package/vendor/gatekeeper/dist/cli/index.js.map +1 -0
- package/vendor/gatekeeper/dist/index.d.ts +9 -0
- package/vendor/gatekeeper/dist/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/index.js +13 -0
- package/vendor/gatekeeper/dist/index.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts +16 -0
- package/vendor/gatekeeper/dist/lib/authz.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/authz.js +42 -0
- package/vendor/gatekeeper/dist/lib/authz.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.d.ts +15 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.js +19 -0
- package/vendor/gatekeeper/dist/lib/cache-bust.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/constants.d.ts +82 -0
- package/vendor/gatekeeper/dist/lib/constants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/constants.js +79 -0
- package/vendor/gatekeeper/dist/lib/constants.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts +32 -0
- package/vendor/gatekeeper/dist/lib/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/grants.js +314 -0
- package/vendor/gatekeeper/dist/lib/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts +10 -0
- package/vendor/gatekeeper/dist/lib/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/groups.js +247 -0
- package/vendor/gatekeeper/dist/lib/groups.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/migration.d.ts +17 -0
- package/vendor/gatekeeper/dist/lib/migration.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/migration.js +79 -0
- package/vendor/gatekeeper/dist/lib/migration.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0001_groups.sql +7 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0002_access_grants.sql +14 -0
- package/vendor/gatekeeper/dist/lib/migrations/gatekeeper/0003_access_request_log.sql +9 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0001_groups.sql +7 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0002_access_grants.sql +14 -0
- package/vendor/gatekeeper/dist/lib/migrations/migrations/gatekeeper/0003_access_request_log.sql +9 -0
- package/vendor/gatekeeper/dist/lib/state-db.d.ts +16 -0
- package/vendor/gatekeeper/dist/lib/state-db.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/state-db.js +154 -0
- package/vendor/gatekeeper/dist/lib/state-db.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts +21 -0
- package/vendor/gatekeeper/dist/lib/templates.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/templates.js +151 -0
- package/vendor/gatekeeper/dist/lib/templates.js.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts +178 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/lib/types.js +2 -0
- package/vendor/gatekeeper/dist/lib/types.js.map +1 -0
- package/vendor/gatekeeper/dist/server/index.d.ts +15 -0
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/index.js +251 -0
- package/vendor/gatekeeper/dist/server/index.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.d.ts +7 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.js +17 -0
- package/vendor/gatekeeper/dist/server/routes/access-request.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/authz.js +279 -0
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts +13 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js +249 -0
- package/vendor/gatekeeper/dist/server/routes/diagnostic.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/grants.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/grants.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/grants.js +112 -0
- package/vendor/gatekeeper/dist/server/routes/grants.js.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/groups.d.ts +3 -0
- package/vendor/gatekeeper/dist/server/routes/groups.d.ts.map +1 -0
- package/vendor/gatekeeper/dist/server/routes/groups.js +139 -0
- package/vendor/gatekeeper/dist/server/routes/groups.js.map +1 -0
- package/vendor/gatekeeper/package.json +49 -0
- package/vendor/server/bin/lamaste-server.js +204 -0
- package/vendor/server/package.json +31 -0
- package/vendor/server/src/commands/certs.js +224 -0
- package/vendor/server/src/commands/chisel.js +132 -0
- package/vendor/server/src/commands/logs.js +49 -0
- package/vendor/server/src/commands/plugins.js +321 -0
- package/vendor/server/src/commands/reset-admin.js +478 -0
- package/vendor/server/src/commands/restart.js +94 -0
- package/vendor/server/src/commands/sites.js +257 -0
- package/vendor/server/src/commands/status.js +158 -0
- package/vendor/server/src/commands/tunnels.js +365 -0
- package/vendor/server/src/commands/uninstall.js +326 -0
- package/vendor/server/src/config.js +38 -0
- package/vendor/server/src/exec.js +26 -0
- package/vendor/server/src/logger.js +39 -0
- package/vendor/server/src/ndjson.js +56 -0
- package/vendor/server/src/panel-api.js +85 -0
- package/vendor/server/src/state.js +45 -0
- package/vendor/server-ui/dist/assets/index-B0nWuUyL.js +257 -0
- package/vendor/server-ui/dist/assets/index-BqWWFlTU.css +1 -0
- package/vendor/server-ui/dist/index.html +13 -0
- package/vendor/serverd/package.json +44 -0
- package/vendor/serverd/src/boot.js +13 -0
- package/vendor/serverd/src/index.js +191 -0
- package/vendor/serverd/src/lib/app-error.js +14 -0
- package/vendor/serverd/src/lib/authelia.js +85 -0
- package/vendor/serverd/src/lib/certbot.js +74 -0
- package/vendor/serverd/src/lib/chisel-args.js +6 -0
- package/vendor/serverd/src/lib/chisel-reconcile.js +232 -0
- package/vendor/serverd/src/lib/chisel-runtime.js +46 -0
- package/vendor/serverd/src/lib/chisel-users.js +109 -0
- package/vendor/serverd/src/lib/chisel.js +81 -0
- package/vendor/serverd/src/lib/config.js +190 -0
- package/vendor/serverd/src/lib/constants.js +8 -0
- package/vendor/serverd/src/lib/csr-signing.js +331 -0
- package/vendor/serverd/src/lib/enrollment.js +302 -0
- package/vendor/serverd/src/lib/files.js +19 -0
- package/vendor/serverd/src/lib/gatekeeper-client.js +135 -0
- package/vendor/serverd/src/lib/invite-page.js +281 -0
- package/vendor/serverd/src/lib/ip-utils.js +79 -0
- package/vendor/serverd/src/lib/migrations/state/0001_enrollment_tokens.sql +17 -0
- package/vendor/serverd/src/lib/migrations/state/0002_tickets.sql +70 -0
- package/vendor/serverd/src/lib/migrations/state/0003_plugins.sql +15 -0
- package/vendor/serverd/src/lib/migrations/state/0004_agents.sql +19 -0
- package/vendor/serverd/src/lib/mtls.js +795 -0
- package/vendor/serverd/src/lib/nginx.js +1090 -0
- package/vendor/serverd/src/lib/pki-paths.js +41 -0
- package/vendor/serverd/src/lib/pki-sign.js +103 -0
- package/vendor/serverd/src/lib/plugins.js +538 -0
- package/vendor/serverd/src/lib/push-install.js +390 -0
- package/vendor/serverd/src/lib/revocation.js +112 -0
- package/vendor/serverd/src/lib/services.js +131 -0
- package/vendor/serverd/src/lib/session.js +151 -0
- package/vendor/serverd/src/lib/state-db.js +130 -0
- package/vendor/serverd/src/lib/state.js +140 -0
- package/vendor/serverd/src/lib/storage.js +63 -0
- package/vendor/serverd/src/lib/system-stats.js +58 -0
- package/vendor/serverd/src/lib/tickets.js +1556 -0
- package/vendor/serverd/src/lib/totp.js +76 -0
- package/vendor/serverd/src/lib/tunnel-deps.js +41 -0
- package/vendor/serverd/src/lib/user-access-session.js +142 -0
- package/vendor/serverd/src/lib/user-access.js +52 -0
- package/vendor/serverd/src/middleware/errors.js +63 -0
- package/vendor/serverd/src/middleware/mtls.js +120 -0
- package/vendor/serverd/src/middleware/onboarding-guard.js +30 -0
- package/vendor/serverd/src/middleware/role-guard.js +58 -0
- package/vendor/serverd/src/middleware/twofa-session.js +65 -0
- package/vendor/serverd/src/middleware/user-access-session.js +52 -0
- package/vendor/serverd/src/routes/enrollment.js +120 -0
- package/vendor/serverd/src/routes/health.js +22 -0
- package/vendor/serverd/src/routes/invite.js +163 -0
- package/vendor/serverd/src/routes/management/agents.js +182 -0
- package/vendor/serverd/src/routes/management/certs.js +911 -0
- package/vendor/serverd/src/routes/management/gatekeeper-proxy.js +160 -0
- package/vendor/serverd/src/routes/management/identity.js +107 -0
- package/vendor/serverd/src/routes/management/invitations.js +166 -0
- package/vendor/serverd/src/routes/management/logs.js +218 -0
- package/vendor/serverd/src/routes/management/plugins.js +560 -0
- package/vendor/serverd/src/routes/management/services.js +63 -0
- package/vendor/serverd/src/routes/management/settings.js +325 -0
- package/vendor/serverd/src/routes/management/sites.js +522 -0
- package/vendor/serverd/src/routes/management/storage.js +192 -0
- package/vendor/serverd/src/routes/management/system.js +201 -0
- package/vendor/serverd/src/routes/management/tickets.js +457 -0
- package/vendor/serverd/src/routes/management/tunnels.js +709 -0
- package/vendor/serverd/src/routes/management/users.js +377 -0
- package/vendor/serverd/src/routes/management.js +36 -0
- package/vendor/serverd/src/routes/onboarding/dns.js +101 -0
- package/vendor/serverd/src/routes/onboarding/domain.js +42 -0
- package/vendor/serverd/src/routes/onboarding/index.js +18 -0
- package/vendor/serverd/src/routes/onboarding/provision.js +327 -0
- package/vendor/serverd/src/routes/onboarding/status.js +12 -0
- package/vendor/serverd/src/routes/plugin-router.js +79 -0
- package/vendor/serverd/src/routes/user-access.js +389 -0
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
# Tickets API
|
|
2
|
+
|
|
3
|
+
> Endpoints for managing agent-to-agent authorization: scope registration, instance management, assignments, ticket operations, and session management.
|
|
4
|
+
|
|
5
|
+
## Authentication
|
|
6
|
+
|
|
7
|
+
All ticket endpoints require mTLS authentication. Endpoints marked "Admin" require an admin certificate. Endpoints marked "Admin/Agent" accept both admin certificates and agent certificates with the appropriate capability.
|
|
8
|
+
|
|
9
|
+
Agent-facing endpoints use generic error messages (404 or 401) for all authorization failures to prevent information leakage.
|
|
10
|
+
|
|
11
|
+
## Scope Management
|
|
12
|
+
|
|
13
|
+
### Register Scope
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
POST /api/tickets/scopes
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Auth:** Admin only
|
|
20
|
+
|
|
21
|
+
Register a new ticket scope (capability set with transport configuration).
|
|
22
|
+
|
|
23
|
+
**Request body:**
|
|
24
|
+
|
|
25
|
+
| Field | Type | Required | Description |
|
|
26
|
+
| ------------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
27
|
+
| `name` | string | Yes | Lowercase alphanumeric with hyphens (1-50 chars). Cannot use reserved names (`tunnels`, `plugins`, `health`, `tickets`, etc.) |
|
|
28
|
+
| `version` | string | Yes | Version string (1-50 chars) |
|
|
29
|
+
| `description` | string | Yes | Human-readable description (1-500 chars) |
|
|
30
|
+
| `scopes` | array | Yes | Capability declarations (1-50 items) |
|
|
31
|
+
| `scopes[].name` | string | Yes | Capability name (e.g., `shell:connect`) |
|
|
32
|
+
| `scopes[].description` | string | Yes | What this capability grants |
|
|
33
|
+
| `scopes[].instanceScoped` | boolean | Yes | Whether tickets are scoped to instances |
|
|
34
|
+
| `transport` | object | Yes | Transport configuration |
|
|
35
|
+
| `transport.strategies` | string[] | Yes | Array of `"tunnel"`, `"relay"`, `"direct"` |
|
|
36
|
+
| `transport.preferred` | string | Yes | Preferred strategy |
|
|
37
|
+
| `transport.port` | number | Yes | Port number (0 or 1024-65535) |
|
|
38
|
+
| `transport.protocol` | string | Yes | `"wss"` or `"tcp"` |
|
|
39
|
+
|
|
40
|
+
**Response (201):**
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"ok": true,
|
|
45
|
+
"registered": ["shell:connect"]
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Errors:** 409 (scope name already registered), 500 (internal error)
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### List Scopes
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
GET /api/tickets/scopes
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Auth:** Admin only
|
|
60
|
+
|
|
61
|
+
Returns all registered scopes, instances, and assignments.
|
|
62
|
+
|
|
63
|
+
**Response (200):**
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"scopes": [...],
|
|
68
|
+
"instances": [...],
|
|
69
|
+
"assignments": [...]
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### Delete Scope
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
DELETE /api/tickets/scopes/:name
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Auth:** Admin only
|
|
82
|
+
|
|
83
|
+
Unregisters a scope and removes its capabilities from the valid capability set.
|
|
84
|
+
|
|
85
|
+
**Response (200):**
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"ok": true,
|
|
90
|
+
"name": "shell"
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Errors:** 404 (scope not found), 500 (internal error)
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Instance Management
|
|
99
|
+
|
|
100
|
+
### Register Instance
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
POST /api/tickets/instances
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Auth:** Admin or Agent (requires base scope capability)
|
|
107
|
+
|
|
108
|
+
Register an instance offering a specific scope. Idempotent: re-registration with the same scope and agent updates transport and resets the heartbeat.
|
|
109
|
+
|
|
110
|
+
**Request body:**
|
|
111
|
+
|
|
112
|
+
| Field | Type | Required | Description |
|
|
113
|
+
| ----------------------- | -------- | -------- | ---------------------------------------------------------------------------------- |
|
|
114
|
+
| `scope` | string | Yes | Capability name in `scope:action` format (e.g., `shell:connect`) |
|
|
115
|
+
| `transport` | object | Yes | Transport configuration |
|
|
116
|
+
| `transport.strategies` | string[] | Yes | Array of `"tunnel"`, `"relay"`, `"direct"` |
|
|
117
|
+
| `transport.preferred` | string | No | Preferred strategy |
|
|
118
|
+
| `transport.direct` | object | No | Direct connection details |
|
|
119
|
+
| `transport.direct.host` | string | Yes\* | Public hostname or IP (1-255 chars). Private/reserved IPs are rejected (see below) |
|
|
120
|
+
| `transport.direct.port` | number | Yes\* | Port number (1024-65535) |
|
|
121
|
+
|
|
122
|
+
\* Required when `transport.direct` is provided.
|
|
123
|
+
|
|
124
|
+
**Host validation:** The `transport.direct.host` field rejects private and reserved addresses to prevent SSRF. The following are rejected with a 400 error:
|
|
125
|
+
|
|
126
|
+
- Private IPv4 ranges: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`
|
|
127
|
+
- Link-local: `169.254.0.0/16`
|
|
128
|
+
- Loopback: `localhost`, `127.0.0.1`, `::1`
|
|
129
|
+
- Metadata endpoints: `169.254.169.254`, `metadata.google.internal`
|
|
130
|
+
- Zero network: `0.0.0.0/8`
|
|
131
|
+
|
|
132
|
+
**Response (201 new, 200 re-registration):**
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"ok": true,
|
|
137
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
138
|
+
"instanceScope": "shell:connect:a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2"
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Errors:** 400 (missing agent label, or private/reserved IP in `transport.direct.host`), 403 (insufficient capability), 404 (scope not found), 503 (hard cap: 200 instances)
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### Deregister Instance
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
DELETE /api/tickets/instances/:instanceId
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Auth:** Admin or owning Agent
|
|
153
|
+
|
|
154
|
+
Removes an instance and cleans up related assignments, tickets, and sessions.
|
|
155
|
+
|
|
156
|
+
**Params:** `instanceId` — hex string (1-128 chars)
|
|
157
|
+
|
|
158
|
+
**Response (200):**
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"ok": true,
|
|
163
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2"
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Errors:** 404 (not found or unauthorized — same response for both)
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### Instance Heartbeat
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
POST /api/tickets/instances/:instanceId/heartbeat
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Auth:** Admin or owning Agent
|
|
178
|
+
|
|
179
|
+
Updates the instance's `lastHeartbeat` timestamp and resets status to active. Re-validates that the owning agent still has the scope capability — returns 404 if the agent is revoked or the capability has been removed.
|
|
180
|
+
|
|
181
|
+
**Response (200):**
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"ok": true
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Errors:** 400 (missing agent label), 404 (not found, or agent revoked/lacks capability)
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Assignment Management
|
|
194
|
+
|
|
195
|
+
### Create Assignment
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
POST /api/tickets/assignments
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Auth:** Admin only
|
|
202
|
+
|
|
203
|
+
Assign an agent to an instance scope, granting it permission to receive tickets for that instance.
|
|
204
|
+
|
|
205
|
+
**Request body:**
|
|
206
|
+
|
|
207
|
+
| Field | Type | Required | Description |
|
|
208
|
+
| --------------- | ------ | -------- | ----------------------------------------------------------------------------------------------- |
|
|
209
|
+
| `agentLabel` | string | Yes | Agent or plugin-agent certificate label (1-150 chars, allows colons for `plugin-agent:` prefix) |
|
|
210
|
+
| `instanceScope` | string | Yes | Format: `scope:action:instanceid` (1-200 chars) |
|
|
211
|
+
|
|
212
|
+
**Validation:**
|
|
213
|
+
|
|
214
|
+
- Agent must exist and not be revoked
|
|
215
|
+
- Agent must have the base scope capability
|
|
216
|
+
- Instance must exist and not be dead
|
|
217
|
+
|
|
218
|
+
**Response (201 new, 200 existing):**
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"ok": true,
|
|
223
|
+
"assignment": {
|
|
224
|
+
"agentLabel": "linux-agent",
|
|
225
|
+
"instanceScope": "shell:connect:a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
226
|
+
"assignedAt": "2026-03-26T10:10:00.000Z",
|
|
227
|
+
"assignedBy": "admin"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Errors:** 400 (agent missing capability), 404 (agent or instance not found)
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### Delete Assignment
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
DELETE /api/tickets/assignments/:agentLabel/:instanceScope
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Auth:** Admin only
|
|
243
|
+
|
|
244
|
+
**Response (200):**
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
{
|
|
248
|
+
"ok": true
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Errors:** 404 (assignment not found)
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### List Assignments
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
GET /api/tickets/assignments
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**Auth:** Admin only
|
|
263
|
+
|
|
264
|
+
**Query params:** `agentLabel` (optional), `instanceScope` (optional) — filters.
|
|
265
|
+
|
|
266
|
+
**Response (200):**
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"assignments": [...]
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Ticket Operations
|
|
277
|
+
|
|
278
|
+
### Request Ticket
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
POST /api/tickets
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Auth:** Admin or Agent (requires base scope capability)
|
|
285
|
+
|
|
286
|
+
Request a ticket to authorize communication with a target agent.
|
|
287
|
+
|
|
288
|
+
**Request body:**
|
|
289
|
+
|
|
290
|
+
| Field | Type | Required | Description |
|
|
291
|
+
| ------------ | ------ | -------- | ------------------------------------------------ |
|
|
292
|
+
| `scope` | string | Yes | Capability name |
|
|
293
|
+
| `instanceId` | string | Yes | Hex instance ID (1-64 chars) |
|
|
294
|
+
| `target` | string | Yes | Target agent or plugin-agent label (1-150 chars) |
|
|
295
|
+
|
|
296
|
+
**Multi-stage validation:**
|
|
297
|
+
|
|
298
|
+
1. Source agent has base scope capability
|
|
299
|
+
2. Target agent has base scope capability and is not revoked
|
|
300
|
+
3. Source owns the instance
|
|
301
|
+
4. Instance is active (not stale or dead)
|
|
302
|
+
5. Source and target are different agents (self-tickets rejected)
|
|
303
|
+
6. Target is assigned to the instance
|
|
304
|
+
|
|
305
|
+
**Response (201):**
|
|
306
|
+
|
|
307
|
+
```json
|
|
308
|
+
{
|
|
309
|
+
"ok": true,
|
|
310
|
+
"ticket": {
|
|
311
|
+
"id": "64-hex-char-ticket-id",
|
|
312
|
+
"scope": "shell:connect",
|
|
313
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
314
|
+
"source": "macbook-pro",
|
|
315
|
+
"target": "linux-agent",
|
|
316
|
+
"expiresAt": "2026-03-26T10:15:30.000Z"
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Errors:** 404 (generic — all authorization failures), 429 (rate limit: 10/min per agent), 503 (stale instance or hard cap: 1000 tickets)
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
### Check Inbox
|
|
326
|
+
|
|
327
|
+
```
|
|
328
|
+
GET /api/tickets/inbox
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**Auth:** Admin or Agent (requires `certLabel`)
|
|
332
|
+
|
|
333
|
+
Returns non-expired, unused tickets where the caller is the target.
|
|
334
|
+
|
|
335
|
+
**Response (200):**
|
|
336
|
+
|
|
337
|
+
```json
|
|
338
|
+
{
|
|
339
|
+
"tickets": [
|
|
340
|
+
{
|
|
341
|
+
"id": "...",
|
|
342
|
+
"scope": "shell:connect",
|
|
343
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
344
|
+
"source": "macbook-pro",
|
|
345
|
+
"expiresAt": "2026-03-26T10:15:30.000Z",
|
|
346
|
+
"transport": {}
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Errors:** 400 (missing certLabel)
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
### Validate Ticket
|
|
357
|
+
|
|
358
|
+
```
|
|
359
|
+
POST /api/tickets/validate
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**Auth:** Admin or Agent (requires `certLabel`)
|
|
363
|
+
|
|
364
|
+
Validate and consume a ticket. This is an atomic operation — the ticket is marked as used on successful validation.
|
|
365
|
+
|
|
366
|
+
**Request body:**
|
|
367
|
+
|
|
368
|
+
| Field | Type | Required | Description |
|
|
369
|
+
| ---------- | ------ | -------- | --------------------------- |
|
|
370
|
+
| `ticketId` | string | Yes | Hex ticket ID (1-128 chars) |
|
|
371
|
+
|
|
372
|
+
**Response (200):**
|
|
373
|
+
|
|
374
|
+
```json
|
|
375
|
+
{
|
|
376
|
+
"valid": true,
|
|
377
|
+
"scope": "shell:connect",
|
|
378
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
379
|
+
"source": "macbook-pro",
|
|
380
|
+
"target": "linux-agent",
|
|
381
|
+
"transport": {}
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
**Errors:** 401 (generic "Invalid ticket" — covers expired, used, wrong target, not found)
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
### List Tickets (Admin)
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
GET /api/tickets
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Auth:** Admin only
|
|
396
|
+
|
|
397
|
+
Returns all tickets (including expired and used).
|
|
398
|
+
|
|
399
|
+
**Response (200):**
|
|
400
|
+
|
|
401
|
+
```json
|
|
402
|
+
{
|
|
403
|
+
"tickets": [...]
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
### Revoke Ticket
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
DELETE /api/tickets/:ticketId
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
**Auth:** Admin only
|
|
416
|
+
|
|
417
|
+
Marks a ticket as used and terminates any associated session.
|
|
418
|
+
|
|
419
|
+
**Response (200):**
|
|
420
|
+
|
|
421
|
+
```json
|
|
422
|
+
{
|
|
423
|
+
"ok": true
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**Errors:** 404 (ticket not found)
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Session Management
|
|
432
|
+
|
|
433
|
+
### Create Session
|
|
434
|
+
|
|
435
|
+
```
|
|
436
|
+
POST /api/tickets/sessions
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
**Auth:** Admin or Agent (requires `certLabel`)
|
|
440
|
+
|
|
441
|
+
Create a session from a validated (used) ticket. The caller must be the ticket's target. The server generates the `sessionId` — clients do not provide it.
|
|
442
|
+
|
|
443
|
+
**Request body:**
|
|
444
|
+
|
|
445
|
+
| Field | Type | Required | Description |
|
|
446
|
+
| ---------- | ------ | -------- | --------------------------- |
|
|
447
|
+
| `ticketId` | string | Yes | Hex ticket ID (1-128 chars) |
|
|
448
|
+
|
|
449
|
+
**Response (201):**
|
|
450
|
+
|
|
451
|
+
```json
|
|
452
|
+
{
|
|
453
|
+
"ok": true,
|
|
454
|
+
"session": {
|
|
455
|
+
"sessionId": "...",
|
|
456
|
+
"ticketId": "...",
|
|
457
|
+
"scope": "shell:connect",
|
|
458
|
+
"instanceId": "a7f3b2c9d1e2f3a4b5c6d7e8f9a0b1c2",
|
|
459
|
+
"source": "macbook-pro",
|
|
460
|
+
"target": "linux-agent",
|
|
461
|
+
"createdAt": "2026-03-26T10:15:30.000Z",
|
|
462
|
+
"lastActivityAt": "2026-03-26T10:15:30.000Z",
|
|
463
|
+
"status": "active",
|
|
464
|
+
"reconnectGraceSeconds": 60
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**Errors:** 400 (invalid ticket state), 409 (duplicate session for ticket), 503 (hard cap: 500 sessions)
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
### Session Heartbeat
|
|
474
|
+
|
|
475
|
+
```
|
|
476
|
+
POST /api/tickets/sessions/:sessionId/heartbeat
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
**Auth:** Admin or Agent (requires `certLabel`)
|
|
480
|
+
|
|
481
|
+
Re-validates the session's authorization and updates activity timestamp.
|
|
482
|
+
|
|
483
|
+
**Validation checks:**
|
|
484
|
+
|
|
485
|
+
1. Session is not dead
|
|
486
|
+
2. Source certificate not revoked
|
|
487
|
+
3. Source has scope capability
|
|
488
|
+
4. Target certificate not revoked
|
|
489
|
+
5. Target has scope capability
|
|
490
|
+
6. Assignment still valid
|
|
491
|
+
|
|
492
|
+
**Response (200):**
|
|
493
|
+
|
|
494
|
+
```json
|
|
495
|
+
{
|
|
496
|
+
"authorized": true
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Or if authorization failed (session is terminated):
|
|
501
|
+
|
|
502
|
+
```json
|
|
503
|
+
{
|
|
504
|
+
"authorized": false,
|
|
505
|
+
"reason": "capability_removed"
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
Possible `reason` values: `admin_killed`, `source_revoked`, `capability_removed`, `target_revoked`, `assignment_removed`.
|
|
510
|
+
|
|
511
|
+
**Errors:** 400 (missing certLabel), 404 (session not found)
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
### Update Session
|
|
516
|
+
|
|
517
|
+
```
|
|
518
|
+
PATCH /api/tickets/sessions/:sessionId
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**Auth:** Admin or Agent (requires `certLabel` — caller can be either the session's source or target)
|
|
522
|
+
|
|
523
|
+
Update session status (e.g., entering grace period for reconnection). Re-validates authorization on every status transition: checks that the source certificate is not revoked, source still has the scope capability, and the target's assignment is still valid. If any check fails, the session is terminated and the endpoint returns 409.
|
|
524
|
+
|
|
525
|
+
**Request body:**
|
|
526
|
+
|
|
527
|
+
| Field | Type | Required | Description |
|
|
528
|
+
| -------- | ------ | -------- | ----------------------- |
|
|
529
|
+
| `status` | string | Yes | `"active"` or `"grace"` |
|
|
530
|
+
|
|
531
|
+
The server sets `lastActivityAt` automatically — clients cannot provide or override this field.
|
|
532
|
+
|
|
533
|
+
**Response (200):**
|
|
534
|
+
|
|
535
|
+
```json
|
|
536
|
+
{
|
|
537
|
+
"ok": true
|
|
538
|
+
}
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
**Errors:** 400 (missing certLabel), 404 (session not found), 409 (session is terminated — dead, or authorization re-validation failed)
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
### Kill Session
|
|
546
|
+
|
|
547
|
+
```
|
|
548
|
+
DELETE /api/tickets/sessions/:sessionId
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
**Auth:** Admin only
|
|
552
|
+
|
|
553
|
+
Immediately terminates a session.
|
|
554
|
+
|
|
555
|
+
**Response (200):**
|
|
556
|
+
|
|
557
|
+
```json
|
|
558
|
+
{
|
|
559
|
+
"ok": true
|
|
560
|
+
}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
**Errors:** 404 (session not found)
|
|
564
|
+
|
|
565
|
+
---
|
|
566
|
+
|
|
567
|
+
### List Sessions
|
|
568
|
+
|
|
569
|
+
```
|
|
570
|
+
GET /api/tickets/sessions
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
**Auth:** Admin only
|
|
574
|
+
|
|
575
|
+
Returns all sessions (including dead ones pending cleanup).
|
|
576
|
+
|
|
577
|
+
**Response (200):**
|
|
578
|
+
|
|
579
|
+
```json
|
|
580
|
+
{
|
|
581
|
+
"sessions": [...]
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## Rate Limiting
|
|
588
|
+
|
|
589
|
+
Ticket requests are rate-limited to **10 per agent per minute**. The rate counter uses a 1-minute window with periodic cleanup every 2 minutes. Exceeding the limit returns:
|
|
590
|
+
|
|
591
|
+
```json
|
|
592
|
+
{
|
|
593
|
+
"error": "Rate limit exceeded"
|
|
594
|
+
}
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
with HTTP 429.
|
|
598
|
+
|
|
599
|
+
## Hard Caps
|
|
600
|
+
|
|
601
|
+
Resource limits protect the 512 MB server:
|
|
602
|
+
|
|
603
|
+
| Resource | Max | HTTP response when exceeded |
|
|
604
|
+
| --------------- | ---- | --------------------------- |
|
|
605
|
+
| Instances | 200 | 503 |
|
|
606
|
+
| Tickets | 1000 | 503 |
|
|
607
|
+
| Active sessions | 500 | 503 |
|
|
608
|
+
|
|
609
|
+
## Cleanup Timers
|
|
610
|
+
|
|
611
|
+
The panel server runs periodic cleanup (every 60 seconds):
|
|
612
|
+
|
|
613
|
+
| Item | Condition | Action |
|
|
614
|
+
| --------------- | ---------------------- | ------------------------------------------- |
|
|
615
|
+
| Stale instances | No heartbeat for 5 min | Status → stale (tickets rejected) |
|
|
616
|
+
| Dead instances | No heartbeat for 1 hr | Removed with assignments, tickets, sessions |
|
|
617
|
+
| Expired tickets | Older than 1 hr | Removed from store |
|
|
618
|
+
| Dead sessions | Dead for 24 hr | Removed from store |
|