@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,375 @@
|
|
|
1
|
+
# Standalone Plugin with Lamaste Tickets
|
|
2
|
+
|
|
3
|
+
> This guide walks through deploying a plugin (e.g., Sync) as a standalone server that uses Lamaste's tunneling and ticket system for authorization — without running the plugin as a Lamaste panel plugin.
|
|
4
|
+
|
|
5
|
+
## Scenario
|
|
6
|
+
|
|
7
|
+
You are an admin who has:
|
|
8
|
+
|
|
9
|
+
1. A **Lamaste server** running on a DigitalOcean droplet
|
|
10
|
+
2. A **Mac** with a Lamaste agent enrolled and a standalone Sync server installed
|
|
11
|
+
3. A **Raspberry Pi** running a Sync agent that needs to sync files with the Sync server
|
|
12
|
+
|
|
13
|
+
The Sync server is **not** a Lamaste plugin — it runs as its own process on its own port. However, it leverages Lamaste for:
|
|
14
|
+
|
|
15
|
+
- **Tunneling** — making the Sync server reachable through a Lamaste subdomain
|
|
16
|
+
- **Tickets** — authorizing which agents can connect to the Sync server
|
|
17
|
+
|
|
18
|
+
## Step-by-Step Walkthrough
|
|
19
|
+
|
|
20
|
+
### 1. Install the Lamaste Desktop App
|
|
21
|
+
|
|
22
|
+
The desktop app is a management shell for existing CLI tools — it does not install them. If the Lamaste agent CLI or Sync CLI are not already installed, install them first.
|
|
23
|
+
|
|
24
|
+
### 2. Provision a Lamaste Server
|
|
25
|
+
|
|
26
|
+
Using the desktop app's cloud provisioning wizard:
|
|
27
|
+
|
|
28
|
+
- Enter your DigitalOcean API token
|
|
29
|
+
- Select a region and droplet size
|
|
30
|
+
- The wizard calls `@lamalibre/lamaste-cloud@4.0.0` to create the droplet
|
|
31
|
+
- Progress streams back as NDJSON events in the desktop UI
|
|
32
|
+
- Complete onboarding in the browser panel
|
|
33
|
+
|
|
34
|
+
### 3. Enroll a Lamaste Agent on the Mac
|
|
35
|
+
|
|
36
|
+
From the Lamaste panel, create an enrollment token with the `plugin:sync:connect` capability (in addition to the default `tunnels:read`). On the Mac, run `lamaste-agent setup` with that token.
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
sequenceDiagram
|
|
40
|
+
participant Admin as Admin (Desktop)
|
|
41
|
+
participant Panel as Lamaste Panel
|
|
42
|
+
participant Mac as Mac (Agent CLI)
|
|
43
|
+
|
|
44
|
+
Admin->>Panel: POST /api/certs/agent/enroll<br/>{label: "macbook-pro",<br/>capabilities: ["tunnels:read", "plugin:sync:connect"]}
|
|
45
|
+
Note over Panel: Generate 32-byte token<br/>10-minute expiry<br/>Store in enrollment-tokens.json
|
|
46
|
+
Panel-->>Admin: {ok, token, expiresAt}
|
|
47
|
+
|
|
48
|
+
Admin-->>Mac: Out-of-band: token + panel URL
|
|
49
|
+
|
|
50
|
+
Mac->>Panel: POST /api/enroll<br/>{token, csr: "<PEM CSR>"}
|
|
51
|
+
Note over Panel: Validate token (HMAC-SHA256 timing-safe)<br/>Consume token (mark used)<br/>Sign CSR with panel CA<br/>Subject: CN=agent:macbook-pro/O=Lamaste<br/>Validity: 730 days<br/>Add to agent registry with capabilities:<br/>["tunnels:read", "plugin:sync:connect"]
|
|
52
|
+
Panel-->>Mac: {ok, cert, caCert, label, serial, expiresAt}
|
|
53
|
+
Note over Mac: Save cert + CA to ~/.lamalibre/lamaste/<br/>Agent is now enrolled
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 4. Install the Sync Server Standalone on the Mac
|
|
57
|
+
|
|
58
|
+
Run the Sync installer on the Mac:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
npx @lamalibre/create-sync
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The installer walks through an interactive setup wizard. On first run, the Sync server generates a one-time **setup token** (printed to console, never persisted). The admin enters this token to generate an **API key** that secures all subsequent API access.
|
|
65
|
+
|
|
66
|
+
```mermaid
|
|
67
|
+
sequenceDiagram
|
|
68
|
+
participant Admin as Admin (Mac terminal)
|
|
69
|
+
participant Installer as create-sync wizard
|
|
70
|
+
participant Server as Sync Server (Mac)
|
|
71
|
+
|
|
72
|
+
Admin->>Installer: npx @lamalibre/create-sync
|
|
73
|
+
|
|
74
|
+
Note over Installer: Check Node.js version<br/>Check rclone installed<br/>Select: Standalone mode
|
|
75
|
+
|
|
76
|
+
Installer->>Server: GET /api/sync/health
|
|
77
|
+
Note over Server: First startup:<br/>No API key exists yet<br/>Generate one-time setup token<br/>Print to console (in-memory only)
|
|
78
|
+
Server-->>Installer: {ok: true}
|
|
79
|
+
|
|
80
|
+
Admin-->>Installer: Enter setup token (from console)
|
|
81
|
+
|
|
82
|
+
Installer->>Server: POST /api/sync/setup/api-key<br/>X-Setup-Token: <token>
|
|
83
|
+
Note over Server: Timing-safe token verification<br/>Generate API key: sync_<32-byte-hex><br/>Store SHA-256 hash in sync-config.json<br/>Discard setup token (one-time use)
|
|
84
|
+
Server-->>Installer: {ok, apiKey: "sync_..."}
|
|
85
|
+
|
|
86
|
+
Note over Admin: Admin must save this API key<br/>It cannot be retrieved again
|
|
87
|
+
|
|
88
|
+
Installer->>Server: PATCH /api/sync/storage<br/>Authorization: Bearer <apiKey><br/>{provider, bucket, accessKey, secretKey, region}
|
|
89
|
+
Note over Server: Test connection to storage<br/>Encrypt credentials with master key<br/>Save to sync-config.json
|
|
90
|
+
Server-->>Installer: {ok}
|
|
91
|
+
|
|
92
|
+
Note over Installer: Optionally: create first project<br/>Install launchd/systemd service<br/>Server is now running
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The Sync server now runs as a local service on the Mac. It operates independently of Lamaste — it has its own API key, its own storage config, and its own agent registry at `~/.sync/agents.json`.
|
|
96
|
+
|
|
97
|
+
### 5. Register Sync Scopes and Instance on Lamaste
|
|
98
|
+
|
|
99
|
+
The Sync server detects that the Mac has a Lamaste agent certificate. Using that cert (mTLS), it registers a ticket scope and instance with the Lamaste panel. This is handled automatically by `TicketInstanceManager` from `@lamalibre/lamaste-tickets@4.0.0` — the admin does not need to do anything.
|
|
100
|
+
|
|
101
|
+
```mermaid
|
|
102
|
+
sequenceDiagram
|
|
103
|
+
participant Sync as Sync Server (Mac)
|
|
104
|
+
participant Panel as Lamaste Panel
|
|
105
|
+
|
|
106
|
+
Note over Sync: Startup: detect Lamaste agent cert<br/>at ~/.lamalibre/lamaste/ → enter plugin mode<br/>mTLS auth: CN=agent:macbook-pro
|
|
107
|
+
|
|
108
|
+
Sync->>Panel: POST /api/tickets/scopes<br/>{name: "sync", version: "1.0.0",<br/>scopes: [{name: "plugin:sync:connect",<br/>instanceScoped: true}],<br/>transport: {strategies: ["tunnel"],<br/>preferred: "tunnel"}}
|
|
109
|
+
Note over Panel: Store scope in ticket-scopes.json<br/>Refresh capability set<br/>(plugin:sync:connect now assignable)
|
|
110
|
+
Panel-->>Sync: {ok, registered: ["plugin:sync:connect"]}
|
|
111
|
+
|
|
112
|
+
Sync->>Panel: POST /api/tickets/instances<br/>{scope: "plugin:sync:connect",<br/>transport: {strategies: ["tunnel"],<br/>preferred: "tunnel"}}
|
|
113
|
+
Note over Panel: Generate instanceId (16 bytes hex)<br/>Bind to agent label: macbook-pro<br/>Status: active
|
|
114
|
+
Panel-->>Sync: {ok, instanceId,<br/>instanceScope: "plugin:sync:connect:<id>"}
|
|
115
|
+
|
|
116
|
+
loop Every 60 seconds
|
|
117
|
+
Sync->>Panel: POST /api/tickets/instances/<instanceId>/heartbeat
|
|
118
|
+
Note over Panel: Update lastHeartbeat<br/>Keep status: active
|
|
119
|
+
Panel-->>Sync: {ok}
|
|
120
|
+
end
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 6. Create a Tunnel for the Sync Server
|
|
124
|
+
|
|
125
|
+
The admin creates a tunnel through Lamaste so the Sync server is reachable from the internet at a subdomain (e.g., `sync.your-domain.com`). The tunnel forwards traffic from the Lamaste droplet through the Mac's Lamaste agent to the local Sync server port. All Lamaste tunnel subdomains are protected by Authelia — unauthenticated requests are redirected to the login portal.
|
|
126
|
+
|
|
127
|
+
### 7. Admin Prepares Agent Enrollment
|
|
128
|
+
|
|
129
|
+
Before the Raspberry Pi can connect, the admin must prepare its enrollment. This is a two-part process: the admin creates the enrollment on the Sync server, and the Sync server pre-announces it to the Lamaste panel.
|
|
130
|
+
|
|
131
|
+
The admin creates a new agent enrollment on the Sync server (e.g., via the Sync CLI or admin API). Because the Sync server detects it is running as a Lamaste agent, it automatically pre-announces to the Lamaste panel, requesting a delegated enrollment token for the new agent.
|
|
132
|
+
|
|
133
|
+
```mermaid
|
|
134
|
+
sequenceDiagram
|
|
135
|
+
participant Admin as Admin (Mac)
|
|
136
|
+
participant Sync as Sync Server (Mac)
|
|
137
|
+
participant Panel as Lamaste Panel
|
|
138
|
+
|
|
139
|
+
Admin->>Sync: Create enrollment for agent "rpi-sync"<br/>Authorization: Bearer <apiKey>
|
|
140
|
+
|
|
141
|
+
Note over Sync: Detect: has Lamaste agent cert<br/>→ pre-announce to Lamaste
|
|
142
|
+
|
|
143
|
+
rect rgb(40, 40, 60)
|
|
144
|
+
Note over Sync,Panel: Pre-announcement (mTLS: CN=agent:macbook-pro)
|
|
145
|
+
Sync->>Panel: POST /api/certs/agent/enroll-delegated<br/>{pluginAgentLabel: "rpi-sync",<br/>scope: "plugin:sync:connect"}
|
|
146
|
+
Note over Panel: Verify caller is agent (not plugin-agent)<br/>Verify plugin:sync:connect is a registered ticket scope<br/>Verify plugin:sync:connect is NOT a base capability<br/>Verify agent owns active instance for scope<br/>Generate delegated token (32 bytes, 10-min expiry)<br/>Store with type: "delegated",<br/>delegatedBy: "macbook-pro",<br/>label: "plugin-agent:macbook-pro:rpi-sync",<br/>capabilities: ["plugin:sync:connect"]
|
|
147
|
+
Panel-->>Sync: {ok, enrollmentToken,<br/>expiresAt, pluginAgentLabel}
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
Sync-->>Admin: Enrollment prepared:<br/>- Sync API key (already known)<br/>- Sync server URL: sync.your-domain.com<br/>- Lamaste delegated token<br/>- Lamaste panel URL
|
|
151
|
+
|
|
152
|
+
Note over Admin: Admin now has everything needed<br/>to set up the Raspberry Pi
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The admin now has four pieces of information to give to the Raspberry Pi:
|
|
156
|
+
|
|
157
|
+
| Credential | Purpose | Source |
|
|
158
|
+
| ----------------------- | ---------------------------------------- | --------------------------------------------------- |
|
|
159
|
+
| Sync API key | Authenticate with the Sync server | From step 4 (already known) |
|
|
160
|
+
| Sync server URL | Where to reach the Sync server | `https://sync.your-domain.com` (the tunnel) |
|
|
161
|
+
| Lamaste delegated token | Enroll with Lamaste to get a certificate | From the pre-announcement (one-time, 10-min expiry) |
|
|
162
|
+
| Lamaste panel URL | Where to submit the enrollment | `https://your-domain.com` |
|
|
163
|
+
|
|
164
|
+
### 8. Raspberry Pi Enrolls with Lamaste
|
|
165
|
+
|
|
166
|
+
The Raspberry Pi must enroll with Lamaste **before** it can access the tunnel. The Lamaste panel's `/api/enroll` endpoint is public — no mTLS or Authelia required. The delegated token is the sole authentication gate.
|
|
167
|
+
|
|
168
|
+
```mermaid
|
|
169
|
+
sequenceDiagram
|
|
170
|
+
participant Admin as Admin
|
|
171
|
+
participant RPi as Raspberry Pi
|
|
172
|
+
participant Panel as Lamaste Panel
|
|
173
|
+
|
|
174
|
+
Admin-->>RPi: Out-of-band: delegated token +<br/>panel URL + API key + tunnel URL
|
|
175
|
+
|
|
176
|
+
Note over RPi: Step 1: Enroll with Lamaste FIRST<br/>(before accessing the tunnel)<br/>Generate RSA 4096-bit keypair<br/>Create CSR via openssl req
|
|
177
|
+
|
|
178
|
+
rect rgb(40, 60, 40)
|
|
179
|
+
Note over RPi,Panel: Lamaste enrollment (public endpoint — no mTLS, no Authelia)
|
|
180
|
+
RPi->>Panel: POST /api/enroll<br/>{token: delegatedToken,<br/>csr: "<PEM CSR>"}
|
|
181
|
+
Note over Panel: Validate token (HMAC-SHA256 timing-safe)<br/>Verify delegating agent (macbook-pro)<br/>still registered and not revoked<br/>Consume token (mark used)<br/>Sign CSR with panel CA<br/>Subject: CN=plugin-agent:macbook-pro:rpi-sync<br/>Validity: 730 days<br/>Add to agent registry:<br/>enrollmentMethod: "delegated"<br/>delegatedBy: "macbook-pro"<br/>capabilities: ["plugin:sync:connect"]
|
|
182
|
+
Panel-->>RPi: {ok, cert, caCert,<br/>label: "plugin-agent:macbook-pro:rpi-sync",<br/>serial, expiresAt}
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
Note over RPi: Save Lamaste cert files to<br/>~/.sync-agent/lamaste-cert/<br/>client.key (mode 0600)<br/>client.crt (mode 0644)<br/>ca.crt (mode 0644)
|
|
186
|
+
|
|
187
|
+
Note over RPi: RPi now has a Lamaste identity<br/>and can access Authelia-protected tunnels
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 9. Raspberry Pi Registers with the Sync Server
|
|
191
|
+
|
|
192
|
+
Now that the RPi has a Lamaste certificate, Authelia can identify it and grant access to the tunnel subdomain. The RPi connects to `sync.your-domain.com` through the Authelia-protected tunnel and registers with the Sync server using the API key.
|
|
193
|
+
|
|
194
|
+
```mermaid
|
|
195
|
+
sequenceDiagram
|
|
196
|
+
participant RPi as Sync Agent (RPi)
|
|
197
|
+
participant Authelia as Authelia
|
|
198
|
+
participant Tunnel as Lamaste Tunnel<br/>sync.your-domain.com
|
|
199
|
+
participant Sync as Sync Server (Mac)
|
|
200
|
+
|
|
201
|
+
Note over RPi: Daemon starts<br/>Has Lamaste cert → can access tunnel<br/>No agentId persisted → must register
|
|
202
|
+
|
|
203
|
+
RPi->>Authelia: Access sync.your-domain.com<br/>(authenticated via Lamaste identity)
|
|
204
|
+
Authelia-->>RPi: Access granted
|
|
205
|
+
|
|
206
|
+
RPi->>Tunnel: POST /api/sync/agents<br/>Authorization: Bearer <apiKey><br/>{name: "rpi-sync",<br/>hostname: "raspberrypi",<br/>os: "Linux",<br/>nodeVersion, agentVersion}
|
|
207
|
+
Tunnel->>Sync: Forward request
|
|
208
|
+
|
|
209
|
+
Note over Sync: Verify API key (SHA-256 + timingSafeEqual)<br/>Generate Sync agent token: agent_<32 hex bytes><br/>Store SHA-256 hash in ~/.sync/agents.json
|
|
210
|
+
|
|
211
|
+
Sync-->>Tunnel: {ok,<br/>agent: {id, name, hostname, status},<br/>agentToken: "agent_..."}
|
|
212
|
+
Tunnel-->>RPi: Forward response
|
|
213
|
+
|
|
214
|
+
Note over RPi: Persist registration:<br/>Save agentId + agentToken<br/>to ~/.sync-agent/agent-settings.json<br/>(AES-256-GCM encrypted at rest)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
After registration, the Sync agent starts its normal operation — fetching config, heartbeating, and syncing files:
|
|
218
|
+
|
|
219
|
+
```mermaid
|
|
220
|
+
sequenceDiagram
|
|
221
|
+
participant RPi as Sync Agent (RPi)
|
|
222
|
+
participant Tunnel as Lamaste Tunnel
|
|
223
|
+
participant Sync as Sync Server (Mac)
|
|
224
|
+
|
|
225
|
+
RPi->>Tunnel: GET /api/sync/agent-config<br/>Authorization: Bearer <apiKey>
|
|
226
|
+
Tunnel->>Sync: Forward
|
|
227
|
+
Note over Sync: Return projects, storage config,<br/>encryption passwords
|
|
228
|
+
Sync-->>Tunnel: {ok, projects, storage, ...}
|
|
229
|
+
Tunnel-->>RPi: Forward
|
|
230
|
+
Note over RPi: Cache config encrypted at<br/>~/.sync-agent/cached-config.json
|
|
231
|
+
|
|
232
|
+
loop Every 15 seconds
|
|
233
|
+
RPi->>Tunnel: POST /api/sync/agents/<agentId>/heartbeat<br/>X-Agent-Token: agent_...<br/>{activeSyncs, diskUsage}
|
|
234
|
+
Tunnel->>Sync: Forward
|
|
235
|
+
Note over Sync: Verify token (SHA-256 + timingSafeEqual)<br/>Update agent status: online
|
|
236
|
+
Sync-->>Tunnel: {ok}
|
|
237
|
+
Tunnel-->>RPi: Forward
|
|
238
|
+
end
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
The Sync agent now has three credentials:
|
|
242
|
+
|
|
243
|
+
| Credential | Purpose | Stored at |
|
|
244
|
+
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
|
|
245
|
+
| Lamaste plugin-agent cert (`CN=plugin-agent:macbook-pro:rpi-sync`) | Authenticate with Authelia to access the tunnel; participate in the Lamaste ticket system | `~/.sync-agent/lamaste-cert/` (PEM files) |
|
|
246
|
+
| Sync API key (`Authorization: Bearer`) | Authenticate with the Sync server for config fetch and registration | `~/.sync-agent/agent-settings.json` (AES-256-GCM encrypted) |
|
|
247
|
+
| Sync agent token (`X-Agent-Token`) | Authenticate with the Sync server for heartbeats and sync reports | `~/.sync-agent/agent-settings.json` (AES-256-GCM encrypted) |
|
|
248
|
+
|
|
249
|
+
### 10. Admin Grants Ticket Access
|
|
250
|
+
|
|
251
|
+
The delegated enrollment gives the Sync agent a Lamaste identity, but it still needs to be authorized in the ticket system. The admin assigns the `plugin:sync:connect` capability and creates a ticket assignment.
|
|
252
|
+
|
|
253
|
+
```mermaid
|
|
254
|
+
sequenceDiagram
|
|
255
|
+
participant Admin as Admin (Panel UI)
|
|
256
|
+
participant Panel as Lamaste Panel
|
|
257
|
+
|
|
258
|
+
Admin->>Panel: PATCH /api/certs/agent/<br/>plugin-agent:macbook-pro:rpi-sync/capabilities<br/>{capabilities: ["plugin:sync:connect"]}
|
|
259
|
+
Note over Panel: Update registry entry<br/>for plugin-agent
|
|
260
|
+
Panel-->>Admin: {ok}
|
|
261
|
+
|
|
262
|
+
Admin->>Panel: POST /api/tickets/assignments<br/>{agentLabel: "plugin-agent:macbook-pro:rpi-sync",<br/>instanceScope: "plugin:sync:connect:<instanceId>"}
|
|
263
|
+
Note over Panel: Store assignment<br/>in ticket-scopes.json
|
|
264
|
+
Panel-->>Admin: {ok}
|
|
265
|
+
|
|
266
|
+
Note over Admin: Plugin-agent can now<br/>participate in plugin:sync:connect tickets
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The plugin-agent cert starts with only the delegated scope capability (`plugin:sync:connect`). The admin can grant additional capabilities via the Certificates page if needed — this is a deliberate opt-in with minimal privilege as the default.
|
|
270
|
+
|
|
271
|
+
### 11. Ticket Authorization in Action
|
|
272
|
+
|
|
273
|
+
With both agents enrolled and the assignment in place, the ticket system authorizes file sync sessions. The Mac (source, instance owner) requests a ticket targeting the RPi's plugin-agent. The RPi polls its inbox, validates the ticket, and establishes a session with heartbeat-based re-validation.
|
|
274
|
+
|
|
275
|
+
```mermaid
|
|
276
|
+
sequenceDiagram
|
|
277
|
+
participant Mac as Sync Server (Mac)<br/>SOURCE: owns instance
|
|
278
|
+
participant Panel as Lamaste Panel
|
|
279
|
+
participant RPi as Sync Agent (RPi)<br/>TARGET: assigned to instance
|
|
280
|
+
|
|
281
|
+
Mac->>Panel: POST /api/tickets<br/>(mTLS: CN=agent:macbook-pro)<br/>{scope: "plugin:sync:connect",<br/>instanceId: "<id>",<br/>target: "plugin-agent:<br/>macbook-pro:rpi-sync"}
|
|
282
|
+
Note over Panel: Rate limit (max 10/min per agent)<br/>Verify source exists, not revoked<br/>Verify source has plugin:sync:connect<br/>Verify target exists, not revoked<br/>Verify target has plugin:sync:connect<br/>Verify source owns instance (not stale)<br/>Verify source ≠ target<br/>Verify target assigned to instance<br/>Generate ticket (32 bytes, 30-sec TTL)
|
|
283
|
+
Panel-->>Mac: {ok, ticket: {id, scope,<br/>instanceId, source, target, expiresAt}}
|
|
284
|
+
|
|
285
|
+
RPi->>Panel: GET /api/tickets/inbox<br/>(mTLS: CN=plugin-agent:<br/>macbook-pro:rpi-sync)
|
|
286
|
+
Panel-->>RPi: {tickets: [{id, scope,<br/>source, expiresAt}]}
|
|
287
|
+
|
|
288
|
+
RPi->>Panel: POST /api/tickets/validate<br/>{ticketId: "<id>"}
|
|
289
|
+
Note over Panel: HMAC-SHA256 timing-safe compare<br/>Verify not expired (30-sec TTL)<br/>Verify not already used<br/>Verify caller is target<br/>Mark ticket as used
|
|
290
|
+
Panel-->>RPi: {valid: true, scope,<br/>instanceId, source, target, transport}
|
|
291
|
+
|
|
292
|
+
RPi->>Panel: POST /api/tickets/sessions<br/>{ticketId: "<id>"}
|
|
293
|
+
Note over Panel: Generate sessionId<br/>(16 bytes, server-side)<br/>Status: active
|
|
294
|
+
Panel-->>RPi: {ok, session: {sessionId,<br/>scope, source, target,<br/>status: "active"}}
|
|
295
|
+
|
|
296
|
+
loop Every 60 seconds
|
|
297
|
+
RPi->>Panel: POST /api/tickets/sessions/<sessionId>/heartbeat
|
|
298
|
+
Note over Panel: Re-validate:<br/>Source not revoked?<br/>Source has capability?<br/>Target not revoked?<br/>Target has capability?<br/>Assignment still valid?
|
|
299
|
+
Panel-->>RPi: {authorized: true}
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
Mac<-->RPi: Sync session authorized — file sync proceeds
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Revocation Cascade
|
|
306
|
+
|
|
307
|
+
If the admin revokes the Mac's Lamaste agent cert (`CN=agent:macbook-pro`), the panel automatically cascade-revokes all plugin-agents delegated by that agent. The Sync agent's cert is revoked in the same atomic operation, and the next session heartbeat terminates the active sync session.
|
|
308
|
+
|
|
309
|
+
```mermaid
|
|
310
|
+
sequenceDiagram
|
|
311
|
+
participant Admin
|
|
312
|
+
participant Panel as Lamaste Panel
|
|
313
|
+
participant RPi as Sync Agent (RPi)
|
|
314
|
+
|
|
315
|
+
Admin->>Panel: DELETE /api/certs/agent/macbook-pro
|
|
316
|
+
|
|
317
|
+
Note over Panel: Revoke agent:macbook-pro<br/>Add serial to revoked.json
|
|
318
|
+
|
|
319
|
+
rect rgb(80, 40, 40)
|
|
320
|
+
Note over Panel: Cascade revocation
|
|
321
|
+
Note over Panel: Find all plugin-agents where<br/>delegatedBy = "macbook-pro"<br/>→ plugin-agent:macbook-pro:rpi-sync
|
|
322
|
+
Note over Panel: Revoke each plugin-agent<br/>Add their serials to revoked.json<br/>Clean up cert files
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
Note over Panel: Save registry atomically
|
|
326
|
+
Panel-->>Admin: {ok}
|
|
327
|
+
|
|
328
|
+
Note over RPi: Next heartbeat...
|
|
329
|
+
RPi->>Panel: POST /api/tickets/sessions/<sessionId>/heartbeat
|
|
330
|
+
Note over Panel: Target cert is revoked
|
|
331
|
+
Panel-->>RPi: {authorized: false,<br/>reason: "target_revoked"}
|
|
332
|
+
Note over RPi: Session terminated<br/>Active syncs cancelled
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Standalone vs Tunneled Behavior
|
|
336
|
+
|
|
337
|
+
The delegated enrollment flow depends on whether the Sync server is reachable through a Lamaste tunnel or directly by IP:
|
|
338
|
+
|
|
339
|
+
| Access method | Lamaste cert? | Ticket authorization |
|
|
340
|
+
| --------------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
341
|
+
| Direct IP (`192.168.1.x:port`) | No — no Lamaste involvement | Sync server mediates tickets on behalf of its agents using its own cert. Two-party model collapses to single party. Sufficient for trusted local networks. |
|
|
342
|
+
| Lamaste tunnel (`sync.your-domain.com`) | Yes — delegated enrollment | Each Sync agent has its own Lamaste identity (`CN=plugin-agent:...`). Full two-party ticket authorization with independent source and target identities. |
|
|
343
|
+
|
|
344
|
+
When the Sync server detects it has a Lamaste agent cert, the admin can prepare agent enrollments that include delegated Lamaste tokens. When running standalone without a Lamaste agent, only the Sync API key is needed and ticket authorization is self-mediated.
|
|
345
|
+
|
|
346
|
+
```mermaid
|
|
347
|
+
flowchart TD
|
|
348
|
+
A[Admin prepares<br/>new agent enrollment<br/>on Sync Server] --> B{Sync Server has<br/>Lamaste agent cert?}
|
|
349
|
+
|
|
350
|
+
B -->|Yes| C[Tunneled Mode]
|
|
351
|
+
B -->|No| D[Standalone Mode]
|
|
352
|
+
|
|
353
|
+
C --> C1[1. Pre-announce to Lamaste panel<br/>POST /api/certs/agent/enroll-delegated]
|
|
354
|
+
C1 --> C2[2. Admin gives RPi: API key +<br/>tunnel URL + delegated token + panel URL]
|
|
355
|
+
C2 --> C3[3. RPi enrolls with Lamaste FIRST<br/>POST /api/enroll — public endpoint]
|
|
356
|
+
C3 --> C4[4. RPi has Lamaste cert<br/>→ can access Authelia-protected tunnel]
|
|
357
|
+
C4 --> C5[5. RPi registers with Sync server<br/>through the tunnel]
|
|
358
|
+
C5 --> C6[Full two-party<br/>ticket authorization]
|
|
359
|
+
|
|
360
|
+
D --> D1[1. Admin gives RPi:<br/>API key + server IP/URL]
|
|
361
|
+
D1 --> D2[2. RPi registers with Sync server<br/>directly via IP]
|
|
362
|
+
D2 --> D3[No Lamaste identity]
|
|
363
|
+
D3 --> D4[Sync server self-mediates<br/>tickets using its own cert]
|
|
364
|
+
|
|
365
|
+
style C fill:#1a3a2a,stroke:#4ade80
|
|
366
|
+
style D fill:#3a2a1a,stroke:#fbbf24
|
|
367
|
+
style C6 fill:#1a3a2a,stroke:#4ade80
|
|
368
|
+
style D4 fill:#3a2a1a,stroke:#fbbf24
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Related Documentation
|
|
372
|
+
|
|
373
|
+
- [Tickets (Agent-to-Agent)](../01-concepts/tickets.md) — ticket system concepts and data model
|
|
374
|
+
- [mTLS & Client Certificates](../01-concepts/mtls.md) — certificate scoping and capabilities
|
|
375
|
+
- [Certificate Management](certificate-management.md) — managing agent certificates
|