@lamalibre/create-lamaste 4.2.0 → 4.3.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/package.json +2 -2
- package/scripts/lamaste-priv +205 -2
- package/src/index.js +4 -4
- package/src/lib/node-version.js +114 -0
- package/src/lib/relay-services.js +15 -1
- package/src/lib/service-config.js +113 -0
- package/src/tasks/gatekeeper.js +8 -3
- package/src/tasks/node.js +34 -75
- package/src/tasks/redeploy.js +36 -0
- package/vendor/docs/00-introduction/how-it-works.md +2 -2
- package/vendor/docs/00-introduction/quickstart.md +5 -5
- package/vendor/docs/00-introduction/what-is-lamaste.md +5 -5
- package/vendor/docs/01-concepts/authentication.md +6 -3
- package/vendor/docs/01-concepts/authorization.md +29 -17
- package/vendor/docs/01-concepts/certificates.md +3 -3
- package/vendor/docs/01-concepts/mtls.md +2 -2
- package/vendor/docs/01-concepts/nginx-reverse-proxy.md +8 -3
- package/vendor/docs/01-concepts/security-model.md +98 -34
- package/vendor/docs/01-concepts/tickets.md +2 -2
- package/vendor/docs/01-concepts/tunneling.md +4 -4
- package/vendor/docs/02-guides/agent-setup.md +34 -16
- package/vendor/docs/02-guides/certificate-management.md +2 -2
- package/vendor/docs/02-guides/cloud-provisioning.md +3 -3
- package/vendor/docs/02-guides/desktop-app-setup.md +10 -10
- package/vendor/docs/02-guides/installation.md +3 -3
- package/vendor/docs/02-guides/onboarding.md +2 -2
- package/vendor/docs/02-guides/standalone-plugin-with-tickets.md +2 -2
- package/vendor/docs/03-architecture/installer-flow.md +2 -2
- package/vendor/docs/03-architecture/installer.md +4 -4
- package/vendor/docs/03-architecture/management-flow.md +1 -1
- package/vendor/docs/03-architecture/nginx-configuration.md +91 -26
- package/vendor/docs/03-architecture/overview.md +8 -8
- package/vendor/docs/03-architecture/panel-client.md +6 -6
- package/vendor/docs/03-architecture/panel-server.md +2 -2
- package/vendor/docs/03-architecture/state-management.md +2 -2
- package/vendor/docs/03-architecture/system-overview.md +1 -1
- package/vendor/docs/04-api-reference/agent-hosted-plugins.md +407 -0
- package/vendor/docs/04-api-reference/app-host.md +360 -0
- package/vendor/docs/04-api-reference/audit-and-notifications.md +57 -0
- package/vendor/docs/04-api-reference/certificates.md +95 -38
- package/vendor/docs/04-api-reference/gatekeeper.md +5 -3
- package/vendor/docs/04-api-reference/lifecycle-hooks.md +333 -0
- package/vendor/docs/04-api-reference/onboarding.md +1 -1
- package/vendor/docs/04-api-reference/overview.md +137 -111
- package/vendor/docs/04-api-reference/registry-and-oidc.md +7 -3
- package/vendor/docs/04-api-reference/tunnels.md +15 -13
- package/vendor/docs/05-operations/backup-and-restore.md +1 -1
- package/vendor/docs/05-operations/uninstalling.md +1 -1
- package/vendor/docs/05-operations/upgrades.md +25 -20
- package/vendor/docs/06-reference/config-files.md +190 -97
- package/vendor/docs/06-reference/glossary.md +3 -3
- package/vendor/docs/06-reference/installer-flags.md +13 -13
- package/vendor/docs/06-reference/ports-and-services.md +1 -1
- package/vendor/docs/06-reference/troubleshooting.md +33 -8
- package/vendor/docs/_index.json +20 -0
- package/vendor/docs/gatekeeper-design.md +22 -19
- package/vendor/docs/identity-directory-design.md +57 -56
- package/vendor/docs/package.json +1 -1
- package/vendor/docs/todo/lib-cli-desktop-refactor.md +27 -27
- package/vendor/gatekeeper/dist/lib/types.d.ts +12 -0
- package/vendor/gatekeeper/dist/lib/types.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.d.ts +2 -0
- package/vendor/gatekeeper/dist/server/index.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/index.js +47 -8
- package/vendor/gatekeeper/dist/server/index.js.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/authz.d.ts.map +1 -1
- package/vendor/gatekeeper/dist/server/routes/authz.js +233 -141
- package/vendor/gatekeeper/dist/server/routes/authz.js.map +1 -1
- package/vendor/gatekeeper/package.json +4 -3
- package/vendor/server/bin/lamaste-server.js +18 -1
- package/vendor/server/package.json +2 -2
- package/vendor/server/src/commands/audit.js +60 -0
- package/vendor/server/src/commands/plugins.js +963 -12
- package/vendor/server/src/commands/push-install.js +317 -0
- package/vendor/server/src/commands/registry-credential.js +2 -1
- package/vendor/server/src/commands/uninstall.js +28 -1
- package/vendor/server/src/ndjson.js +4 -2
- package/vendor/server/src/panel-api.js +32 -4
- package/vendor/server-ui/dist/assets/index-Bc5NCMSv.css +1 -0
- package/vendor/server-ui/dist/assets/index-DBp3cmaU.js +84 -0
- package/vendor/server-ui/dist/index.html +2 -2
- package/vendor/serverd/package.json +2 -2
- package/vendor/serverd/src/index.js +56 -4
- package/vendor/serverd/src/lib/actor.js +24 -0
- package/vendor/serverd/src/lib/agent-jobs.js +330 -0
- package/vendor/serverd/src/lib/app-error.js +10 -0
- package/vendor/serverd/src/lib/audit.js +145 -0
- package/vendor/serverd/src/lib/hook-effects.js +123 -0
- package/vendor/serverd/src/lib/hook-pipelines.js +902 -0
- package/vendor/serverd/src/lib/migrations/state/0006_plugin_agent.sql +4 -0
- package/vendor/serverd/src/lib/migrations/state/0007_audit_and_notifications.sql +29 -0
- package/vendor/serverd/src/lib/migrations/state/0008_plugin_hooks.sql +70 -0
- package/vendor/serverd/src/lib/migrations/state/0009_plugin_agent_half.sql +53 -0
- package/vendor/serverd/src/lib/migrations/state/0010_plugin_routes_and_retained_data.sql +47 -0
- package/vendor/serverd/src/lib/migrations/state/0011_agent_job_signature.sql +14 -0
- package/vendor/serverd/src/lib/mtls.js +89 -8
- package/vendor/serverd/src/lib/nginx.js +298 -44
- package/vendor/serverd/src/lib/notifications.js +107 -0
- package/vendor/serverd/src/lib/plugin-hooks.js +560 -0
- package/vendor/serverd/src/lib/plugin-hosting.js +688 -0
- package/vendor/serverd/src/lib/plugin-lifecycle.js +603 -0
- package/vendor/serverd/src/lib/plugin-operations.js +295 -0
- package/vendor/serverd/src/lib/plugin-packages.js +249 -0
- package/vendor/serverd/src/lib/plugins.js +298 -68
- package/vendor/serverd/src/lib/push-install.js +88 -2
- package/vendor/serverd/src/lib/relay-hooks.js +100 -0
- package/vendor/serverd/src/lib/relay-signing.js +43 -0
- package/vendor/serverd/src/lib/request-hooks.js +79 -0
- package/vendor/serverd/src/lib/retained-data.js +99 -0
- package/vendor/serverd/src/lib/trust-proxy.js +34 -0
- package/vendor/serverd/src/lib/tunnel-hooks.js +88 -0
- package/vendor/serverd/src/lib/vhost-reconcile.js +260 -0
- package/vendor/serverd/src/middleware/twofa-session.js +11 -1
- package/vendor/serverd/src/routes/agent-forwarder.js +37 -0
- package/vendor/serverd/src/routes/management/agent-panel-authz.js +97 -0
- package/vendor/serverd/src/routes/management/agents.js +262 -1
- package/vendor/serverd/src/routes/management/audit.js +81 -0
- package/vendor/serverd/src/routes/management/certs.js +1 -15
- package/vendor/serverd/src/routes/management/plugins.js +569 -54
- package/vendor/serverd/src/routes/management/tunnels.js +26 -0
- package/vendor/serverd/src/routes/management.js +4 -0
- package/vendor/server-ui/dist/assets/index-B5Wp8lu-.js +0 -257
- package/vendor/server-ui/dist/assets/index-BqWWFlTU.css +0 -1
|
@@ -217,7 +217,7 @@ The agent's sync timer applies tunnel changes within about 30 seconds. If that d
|
|
|
217
217
|
lamaste-agent update # apply now and (re)install the sync timer
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
`update` needs the agent installed globally (`npm install -g @lamalibre/lamaste-agent@4.
|
|
220
|
+
`update` needs the agent installed globally (`npm install -g @lamalibre/lamaste-agent@4.3.0`); an agent originally set up with `npx` must be installed first.
|
|
221
221
|
|
|
222
222
|
**Cause 3: The agent does not carry the tunnel.**
|
|
223
223
|
|
|
@@ -320,7 +320,7 @@ ls -la /usr/local/bin/authelia
|
|
|
320
320
|
| Missing `panel.json` | `Config file not found` | Re-run installer or create the file manually |
|
|
321
321
|
| Invalid JSON in `panel.json` | `contains invalid JSON` | Fix the JSON syntax |
|
|
322
322
|
| Port 3100 in use | `EADDRINUSE` | Find and stop the conflicting process: `sudo ss -tlnp sport = :3100` |
|
|
323
|
-
| Missing Node.js modules | `Cannot find module` | Re-run the installer (`npx @lamalibre/create-lamaste@4.
|
|
323
|
+
| Missing Node.js modules | `Cannot find module` | Re-run the installer (`npx @lamalibre/create-lamaste@4.3.0 --yes`); `/opt/lamalibre/lamaste` is root-owned and redeployed as a whole |
|
|
324
324
|
| Permission denied writing state | `EACCES` under `/etc/lamalibre/lamaste` | Re-run the installer; the redeploy re-applies the ownership of the config and PKI directories |
|
|
325
325
|
|
|
326
326
|
### chisel fails to start
|
|
@@ -329,7 +329,7 @@ ls -la /usr/local/bin/authelia
|
|
|
329
329
|
|
|
330
330
|
| Cause | Log Message | Fix |
|
|
331
331
|
| -------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
332
|
-
| Binary missing | `exec format error` or `not found` | Re-run the installer (`npx @lamalibre/create-lamaste@4.
|
|
332
|
+
| Binary missing | `exec format error` or `not found` | Re-run the installer (`npx @lamalibre/create-lamaste@4.3.0 --yes`) — it installs the pinned, checksum-verified release for the server's architecture; the panel cannot install binaries |
|
|
333
333
|
| Not the pinned release | (panel log) `The installed chisel is not the pinned release — run create-lamaste ...` | Re-run the installer. Until then the panel restarts Chisel on every authfile change |
|
|
334
334
|
| Authfile or key unreadable | `permission denied` on `chisel-users` or `chisel-server.key` | Both must be `0640 lamaste:lamaste-chisel` and the unit `Group=lamaste-chisel`; restart the panel, which re-applies the authfile's. If the group, the unit or the key's ownership is wrong, re-run the installer in redeploy mode |
|
|
335
335
|
| Stopped by the panel | (panel log) `Chisel stopped: ...`; unit disabled, `chisel-failed-closed` present | Reconciliation failed closed; see [Tunnel Client Cannot Connect](#tunnel-client-cannot-connect), Cause 1 |
|
|
@@ -343,7 +343,7 @@ ls -la /usr/local/bin/authelia
|
|
|
343
343
|
| --------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
344
344
|
| Invalid `configuration.yml` | `configuration: error` | Check YAML syntax with `authelia validate-configuration --config /etc/authelia/configuration.yml` |
|
|
345
345
|
| Missing `users.yml` | `cannot open file` | Create an initial users file (see [Config Files](config-files.md)) |
|
|
346
|
-
| Binary missing | `not found` | Re-run the installer (`npx @lamalibre/create-lamaste@4.
|
|
346
|
+
| Binary missing | `not found` | Re-run the installer (`npx @lamalibre/create-lamaste@4.3.0 --yes`); it installs the pinned release |
|
|
347
347
|
| Wrong permissions | `permission denied` | Authelia runs as `lamaste-authelia`: `/etc/authelia` must be `lamaste:lamaste-authelia 2770`, `configuration.yml` `0640`, `users.yml` `0660`, `db.sqlite3` owned by `lamaste-authelia`. Re-run the installer to re-apply (a root-owned `/etc/authelia` from an older version is converted), or see [Config Files](config-files.md#file-permissions-table) |
|
|
348
348
|
| Database newer than binary | storage schema version error at startup | A newer Authelia ran against this database and was replaced by an older one; the installer never downgrades an installed Authelia, so reinstall that newer release by hand |
|
|
349
349
|
|
|
@@ -516,14 +516,14 @@ sudo systemctl restart authelia
|
|
|
516
516
|
|
|
517
517
|
## Onboarding Fails: "Chisel is not installed" / "Authelia is not installed"
|
|
518
518
|
|
|
519
|
-
**Symptom:** The **Starting Chisel** or **Configuring Authelia** provisioning task fails with "Chisel is not installed. Run `npx @lamalibre/create-lamaste@4.
|
|
519
|
+
**Symptom:** The **Starting Chisel** or **Configuring Authelia** provisioning task fails with "Chisel is not installed. Run `npx @lamalibre/create-lamaste@4.3.0` on the server to repair the installation." (or the same for Authelia).
|
|
520
520
|
|
|
521
521
|
**Cause:** Onboarding downloads nothing: the installer installs both binaries (pinned releases), their systemd units and the `lamaste-authelia` account. The binary at `/usr/local/bin/chisel` or `/usr/local/bin/authelia` is missing — the installer was interrupted, or the file was removed.
|
|
522
522
|
|
|
523
523
|
**Fix:** Re-run the installer on the server, then start provisioning again from the wizard:
|
|
524
524
|
|
|
525
525
|
```bash
|
|
526
|
-
npx @lamalibre/create-lamaste@4.
|
|
526
|
+
npx @lamalibre/create-lamaste@4.3.0 --yes
|
|
527
527
|
```
|
|
528
528
|
|
|
529
529
|
If provisioning then fails writing Authelia's configuration with `/etc/authelia is not writable by the panel — run create-lamaste to repair the installation`, the directory's ownership is wrong; the same command repairs it.
|
|
@@ -538,7 +538,7 @@ If provisioning then fails writing Authelia's configuration with `/etc/authelia
|
|
|
538
538
|
|
|
539
539
|
**Fix:**
|
|
540
540
|
|
|
541
|
-
1. Re-run the installer so the helper matches the panel: `npx @lamalibre/create-lamaste@4.
|
|
541
|
+
1. Re-run the installer so the helper matches the panel: `npx @lamalibre/create-lamaste@4.3.0 --yes`
|
|
542
542
|
2. If it persists on a current install, it is a bug: the vhost generators (`packages/server/daemon/src/lib/nginx.js`) and the allow-list (`packages/provisioners/server/scripts/lamaste-priv`) must change together — `npm test` checks every generated vhost against the allow-list. Do not work around it by editing files in `/etc/nginx` by hand.
|
|
543
543
|
|
|
544
544
|
`sudo: a password is required` for `lamaste-priv` means the helper or the sudoers file is missing or outdated: re-run the installer.
|
|
@@ -621,7 +621,7 @@ df -h /
|
|
|
621
621
|
|
|
622
622
|
**Cause 3: The web root is not writable by the panel (`EACCES`).**
|
|
623
623
|
|
|
624
|
-
The panel writes `/var/www/lamaste` itself: it must be `lamaste:www-data`, directories `2750`, files `0640`. An install from before this layout had it owned by `www-data`. Re-run the installer (`npx @lamalibre/create-lamaste@4.
|
|
624
|
+
The panel writes `/var/www/lamaste` itself: it must be `lamaste:www-data`, directories `2750`, files `0640`. An install from before this layout had it owned by `www-data`. Re-run the installer (`npx @lamalibre/create-lamaste@4.3.0 --yes`); the redeploy converts the tree.
|
|
625
625
|
|
|
626
626
|
---
|
|
627
627
|
|
|
@@ -642,6 +642,31 @@ curl -s --cert client.p12:password \
|
|
|
642
642
|
|
|
643
643
|
---
|
|
644
644
|
|
|
645
|
+
## Agent Panel or Plugin Tunnel Answers 401 Through the Relay
|
|
646
|
+
|
|
647
|
+
**Symptom:** `https://agent-<label>.<domain>/` (with a valid certificate) or a plugin tunnel (after the Authelia login) answers `401 {"error":"Unauthorized"}`, while the agent's own desktop app works.
|
|
648
|
+
|
|
649
|
+
**Cause:** From 4.3, lamaste-agentd accepts a request from the relay only with a relay assertion it can verify (see [Security Model](../01-concepts/security-model.md#5c-the-agent-daemon-lamaste-agentd-and-relay-assertions)). The daemon's log (`~/.lamalibre/lamaste/agents/<label>/logs/panel.log`) names the reason:
|
|
650
|
+
|
|
651
|
+
- `Failed to fetch relay verification keys` — the daemon cannot reach `GET /api/agents/me/relay-keys` on the panel: the relay is older than 4.3 (upgrade the relay — it is the side that must be upgraded first), or the panel is unreachable from the agent.
|
|
652
|
+
- `Relay assertion refused` with `reason: "future"` or `"expired"` — the agent's clock differs from the relay's by more than a few seconds. Assertions are valid for 60 seconds with 5 seconds of skew; enable NTP on both.
|
|
653
|
+
- `reason: "unknown_key"` — the relay's key was replaced less than 30 seconds ago; the daemon fetches the new one on the next request after that.
|
|
654
|
+
- Nothing logged but the `401` itself — no assertion arrived: the vhost predates 4.3 and the panel's startup reconcile could not rewrite it (the panel log at startup names it: `Failed to rewrite tunnel vhost`). On the server, `grep -c 'auth_request /internal/lamaste/agent-panel-authz;' /etc/nginx/sites-available/lamalibre-lamaste-agent-panel-agent-<label>` must print `1`.
|
|
655
|
+
|
|
656
|
+
A request sent straight to the daemon's port with `X-SSL-Client-*` or `Remote-User` headers is refused by design: those headers prove nothing.
|
|
657
|
+
|
|
658
|
+
---
|
|
659
|
+
|
|
660
|
+
## A Tunnel Answers 403 for Everyone After the Upgrade to 4.3
|
|
661
|
+
|
|
662
|
+
**Symptom:** an `authenticated` or `restricted` tunnel answers `403` to every user — grantees included — and a restricted tunnel shows "This tunnel is unavailable until the relay rewrites its configuration." Gatekeeper's log (`journalctl -u lamalibre-lamaste-gatekeeper`) has `authz refused` with `reason: "vhost_predates_host_binding"`.
|
|
663
|
+
|
|
664
|
+
**Cause:** the tunnel's vhost was written before 4.3 and still asks Gatekeeper's `/authz/check` with the client's `Host` header, which let a user allowed on one tunnel into another (see [nginx Configuration](../03-architecture/nginx-configuration.md#authorization-subrequests-name-their-own-hostname)). Gatekeeper 4.3 refuses that subrequest, so such a vhost closes its tunnel. The panel rewrites tunnel vhosts when it starts; this one was not rewritten.
|
|
665
|
+
|
|
666
|
+
**Fix:** the panel's startup log (`journalctl -u lamalibre-lamaste-serverd`) names the tunnel under `Left tunnel vhosts as they are` (with the reason) or `Failed to rewrite tunnel vhost` (with the `nginx -t` or certificate error). Fix that, then `sudo systemctl restart lamalibre-lamaste-serverd`. On the server, `grep -c 'authz/tunnel/<fqdn>;' /etc/nginx/sites-available/lamalibre-lamaste-app-<subdomain>` must print `1`. The same log lines name static sites (`Left site vhosts as they are`, `Failed to rewrite site vhost`): a site vhost that was not rewritten still names the client's `Host` to Authelia, so treat those first.
|
|
667
|
+
|
|
668
|
+
---
|
|
669
|
+
|
|
645
670
|
## Quick Reference: Diagnostic Commands
|
|
646
671
|
|
|
647
672
|
| What to Check | Command |
|
package/vendor/docs/_index.json
CHANGED
|
@@ -196,6 +196,26 @@
|
|
|
196
196
|
"title": "Registry Credential & OIDC Clients",
|
|
197
197
|
"slug": "api-registry-and-oidc",
|
|
198
198
|
"file": "04-api-reference/registry-and-oidc.md"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"title": "Agent-Hosted Plugins",
|
|
202
|
+
"slug": "api-agent-hosted-plugins",
|
|
203
|
+
"file": "04-api-reference/agent-hosted-plugins.md"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"title": "App Host (Agent Halves)",
|
|
207
|
+
"slug": "api-app-host",
|
|
208
|
+
"file": "04-api-reference/app-host.md"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"title": "Lifecycle Hooks",
|
|
212
|
+
"slug": "api-lifecycle-hooks",
|
|
213
|
+
"file": "04-api-reference/lifecycle-hooks.md"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"title": "Audit Log & Notifications",
|
|
217
|
+
"slug": "api-audit-and-notifications",
|
|
218
|
+
"file": "04-api-reference/audit-and-notifications.md"
|
|
199
219
|
}
|
|
200
220
|
]
|
|
201
221
|
},
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
`@lamalibre/lamaste-gatekeeper@4.
|
|
5
|
+
`@lamalibre/lamaste-gatekeeper@4.3.0` is a standalone authorization package for Lamaste. It manages **groups** and **grants**, enforces tunnel access control via a lightweight Fastify service, and serves user-friendly "request access" pages when access is denied.
|
|
6
6
|
|
|
7
|
-
It follows the same architectural pattern as `@lamalibre/lamaste-tickets@4.
|
|
7
|
+
It follows the same architectural pattern as `@lamalibre/lamaste-tickets@4.3.0` — a solid library at the core, with a service, CLI, and desktop as consumers.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -78,7 +78,7 @@ packages/lamaste-gatekeeper/
|
|
|
78
78
|
server/
|
|
79
79
|
index.js # Fastify service entry point (127.0.0.1:9294)
|
|
80
80
|
routes/
|
|
81
|
-
authz.js # GET /authz/
|
|
81
|
+
authz.js # GET /authz/tunnel/:fqdn — nginx auth_request target
|
|
82
82
|
access-request.js # GET /access-request — denial page with message templates
|
|
83
83
|
groups.js # REST API for group management
|
|
84
84
|
grants.js # REST API for grant management
|
|
@@ -204,7 +204,7 @@ The grant system is resource-agnostic. It doesn't know what a "tunnel" or "plugi
|
|
|
204
204
|
|
|
205
205
|
```js
|
|
206
206
|
import { createGroup, listGroups, getGroup, updateGroup, deleteGroup,
|
|
207
|
-
addMembers, removeMembers, getGroupsForUser } from '@lamalibre/lamaste-gatekeeper@4.
|
|
207
|
+
addMembers, removeMembers, getGroupsForUser } from '@lamalibre/lamaste-gatekeeper@4.3.0';
|
|
208
208
|
|
|
209
209
|
createGroup(name, { description?, createdBy? })
|
|
210
210
|
// → { name, description, members: [], createdAt, createdBy }
|
|
@@ -240,7 +240,7 @@ getGroupsForUser(username)
|
|
|
240
240
|
### Grants
|
|
241
241
|
|
|
242
242
|
```js
|
|
243
|
-
import { createGrant, listGrants, getGrant, revokeGrant } from '@lamalibre/lamaste-gatekeeper@4.
|
|
243
|
+
import { createGrant, listGrants, getGrant, revokeGrant } from '@lamalibre/lamaste-gatekeeper@4.3.0';
|
|
244
244
|
|
|
245
245
|
createGrant({ principalType, principalId, resourceType, resourceId, context? })
|
|
246
246
|
// → grant object
|
|
@@ -267,7 +267,7 @@ revokeGrant(grantId)
|
|
|
267
267
|
### Authorization
|
|
268
268
|
|
|
269
269
|
```js
|
|
270
|
-
import { checkAccess } from '@lamalibre/lamaste-gatekeeper@4.
|
|
270
|
+
import { checkAccess } from '@lamalibre/lamaste-gatekeeper@4.3.0';
|
|
271
271
|
|
|
272
272
|
checkAccess(username, resourceType, resourceId);
|
|
273
273
|
// 1. Find direct user grants: principalType='user', principalId=username
|
|
@@ -282,7 +282,7 @@ checkAccess(username, resourceType, resourceId);
|
|
|
282
282
|
### Templates
|
|
283
283
|
|
|
284
284
|
```js
|
|
285
|
-
import { getAccessRequestTemplates } from '@lamalibre/lamaste-gatekeeper@4.
|
|
285
|
+
import { getAccessRequestTemplates } from '@lamalibre/lamaste-gatekeeper@4.3.0';
|
|
286
286
|
|
|
287
287
|
getAccessRequestTemplates(username, resourceName, { adminContact?, domain? })
|
|
288
288
|
// → {
|
|
@@ -316,9 +316,9 @@ proxy_cache_path /var/cache/nginx/authz levels=1:2
|
|
|
316
316
|
|
|
317
317
|
location /internal/lamaste/authz {
|
|
318
318
|
internal;
|
|
319
|
-
proxy_pass http://127.0.0.1:9294/authz/
|
|
319
|
+
proxy_pass http://127.0.0.1:9294/authz/tunnel/gitlab.example.com;
|
|
320
320
|
proxy_cache authz_cache;
|
|
321
|
-
proxy_cache_key "$cookie_authelia_session
|
|
321
|
+
proxy_cache_key "$server_name|$cookie_authelia_session"; # the vhost, never the client's Host
|
|
322
322
|
proxy_cache_valid 200 30s; # cache successful auth for 30s
|
|
323
323
|
proxy_cache_valid 403 10s; # cache denial for 10s (shorter — revocations take effect faster)
|
|
324
324
|
# Never cache 401 — user needs fresh login redirect
|
|
@@ -416,10 +416,13 @@ server {
|
|
|
416
416
|
# Gatekeeper auth (handles both authentication via Authelia + authorization via grants)
|
|
417
417
|
location /internal/lamaste/authz {
|
|
418
418
|
internal;
|
|
419
|
-
|
|
420
|
-
|
|
419
|
+
# The tunnel in the path and the vhost's own hostname in the headers,
|
|
420
|
+
# never $http_host: an absolute-form request line selects this vhost
|
|
421
|
+
# while the client's Host names another tunnel
|
|
422
|
+
proxy_pass http://127.0.0.1:9294/authz/tunnel/gitlab.example.com;
|
|
423
|
+
proxy_set_header X-Original-URL https://gitlab.example.com$request_uri;
|
|
421
424
|
proxy_set_header X-Forwarded-For $remote_addr;
|
|
422
|
-
proxy_set_header Host
|
|
425
|
+
proxy_set_header Host gitlab.example.com;
|
|
423
426
|
proxy_pass_request_body off;
|
|
424
427
|
proxy_set_header Content-Length "";
|
|
425
428
|
# Forward cookies so gatekeeper can validate Authelia session
|
|
@@ -434,10 +437,10 @@ server {
|
|
|
434
437
|
auth_request_set $remote_email $upstream_http_remote_email;
|
|
435
438
|
|
|
436
439
|
# Authentication failure → Authelia login
|
|
437
|
-
error_page 401 =302 https://auth.example.com/?rd
|
|
440
|
+
error_page 401 =302 https://auth.example.com/?rd=https://gitlab.example.com$request_uri;
|
|
438
441
|
|
|
439
442
|
# Authorization failure → access request page
|
|
440
|
-
error_page 403 =302 https://auth.example.com/access-request?tunnel
|
|
443
|
+
error_page 403 =302 https://auth.example.com/access-request?tunnel=gitlab.example.com;
|
|
441
444
|
|
|
442
445
|
# Set headers for backend
|
|
443
446
|
proxy_set_header Remote-User $remote_user;
|
|
@@ -456,13 +459,13 @@ server {
|
|
|
456
459
|
|
|
457
460
|
### Authz Check Endpoint
|
|
458
461
|
|
|
459
|
-
`GET /authz/check
|
|
462
|
+
`GET /authz/tunnel/:fqdn` (vhosts before 4.3 called `GET /authz/check`, which is now refused — see [nginx Configuration](03-architecture/nginx-configuration.md#authorization-subrequests-name-their-own-hostname))
|
|
460
463
|
|
|
461
|
-
1. Read `Cookie` and `X-Original-URL` headers from nginx
|
|
464
|
+
1. Read `Cookie` and `X-Original-URL` headers from nginx; the tunnel is the one named in the path, and `X-Original-URL` and `Host` must name it too
|
|
462
465
|
2. Forward cookie to Authelia's verification endpoint (`http://127.0.0.1:9091/api/authz/forward-auth`)
|
|
463
466
|
3. If Authelia returns 401 → return 401 (not authenticated)
|
|
464
467
|
4. If Authelia returns 200 → extract `Remote-User`, `Remote-Groups`, `Remote-Name`, `Remote-Email` from Authelia response headers
|
|
465
|
-
5.
|
|
468
|
+
5. Look up the tunnel named in the path
|
|
466
469
|
6. Check tunnel's `accessMode`:
|
|
467
470
|
- `public` → return 200 (should not reach here, but safe fallback)
|
|
468
471
|
- `authenticated` → return 200 (Authelia passed = sufficient)
|
|
@@ -861,14 +864,14 @@ On first startup, gatekeeper checks for legacy files:
|
|
|
861
864
|
|
|
862
865
|
### Panel-Server Refactoring
|
|
863
866
|
|
|
864
|
-
- `lib/user-access.js` → delegates to gatekeeper library (import from `@lamalibre/lamaste-gatekeeper@4.
|
|
867
|
+
- `lib/user-access.js` → delegates to gatekeeper library (import from `@lamalibre/lamaste-gatekeeper@4.3.0`)
|
|
865
868
|
- `lib/access-control-sync.js` → removed (gatekeeper handles authorization at nginx layer, no more Authelia config rewriting for per-user access rules)
|
|
866
869
|
- `routes/user-access.js` → simplified, delegates grant CRUD to gatekeeper
|
|
867
870
|
- Tunnel creation/update routes → call gatekeeper for access mode changes
|
|
868
871
|
|
|
869
872
|
### Installer Updates (create-lamaste)
|
|
870
873
|
|
|
871
|
-
- Install `@lamalibre/lamaste-gatekeeper@4.
|
|
874
|
+
- Install `@lamalibre/lamaste-gatekeeper@4.3.0` package
|
|
872
875
|
- Create `/etc/lamalibre/lamaste/groups.json` (empty initial state)
|
|
873
876
|
- Create `/etc/lamalibre/lamaste/access-grants.json` (empty or migrated)
|
|
874
877
|
- Create `lamalibre-lamaste-gatekeeper.service` systemd unit
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Lamaste Identity Directory — Design Document
|
|
2
2
|
|
|
3
3
|
> **Status:** design, 2026-10-13. Nothing here is implemented yet.
|
|
4
|
-
> **Package:** `@lamalibre/lamaste-identity@4.
|
|
4
|
+
> **Package:** `@lamalibre/lamaste-identity@4.3.0` (completes the existing SDK).
|
|
5
5
|
> **Companions:** `gatekeeper-design.md` (authorization),
|
|
6
6
|
> `plugin-development/design/agent-hosted-app-plugins.md` (app plugins).
|
|
7
7
|
|
|
@@ -28,15 +28,15 @@ copy to follow Lamaste.
|
|
|
28
28
|
|
|
29
29
|
## What exists today
|
|
30
30
|
|
|
31
|
-
| Piece
|
|
32
|
-
|
|
33
|
-
| User store
|
|
34
|
-
| `GET /api/identity/users`, `/users/:username`, `/groups` | Read `users.yml`; admin or agent with `identity:query`.
|
|
35
|
-
| `GET /api/identity/self`
|
|
36
|
-
| SDK `IdentityClient`
|
|
37
|
-
| SDK `parseIdentity` + Fastify plugin
|
|
38
|
-
| Tunnel vhosts
|
|
39
|
-
| Entitlements
|
|
31
|
+
| Piece | State |
|
|
32
|
+
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
33
|
+
| User store | Authelia's `users.yml`, keyed by **username**. No stable id. |
|
|
34
|
+
| `GET /api/identity/users`, `/users/:username`, `/groups` | Read `users.yml`; admin or agent with `identity:query`. |
|
|
35
|
+
| `GET /api/identity/self` | Echoes `Remote-*` headers; only meaningful behind Authelia. |
|
|
36
|
+
| SDK `IdentityClient` | `listUsers`, `getUser`, `listGroups` over mTLS. |
|
|
37
|
+
| SDK `parseIdentity` + Fastify plugin | Parses `Remote-User/Name/Email/Groups` headers. |
|
|
38
|
+
| Tunnel vhosts | **Blank** `Remote-User` and `Remote-Groups` before proxying — apps receive no identity. |
|
|
39
|
+
| Entitlements | Two models: per-plugin grants (`user-plugin-access.json`, by username) and Gatekeeper grants (groups → resources). |
|
|
40
40
|
|
|
41
41
|
So the SDK can list users, but nothing gives an application a stable key, a
|
|
42
42
|
scoped user list, a change feed, or a trustworthy identity on a request.
|
|
@@ -53,15 +53,15 @@ The directory record Lamaste owns:
|
|
|
53
53
|
|
|
54
54
|
```ts
|
|
55
55
|
interface DirectoryUser {
|
|
56
|
-
userId: string;
|
|
57
|
-
username: string;
|
|
56
|
+
userId: string; // UUID, never reused
|
|
57
|
+
username: string; // login name, unique, may change
|
|
58
58
|
displayName: string;
|
|
59
59
|
email: string;
|
|
60
|
-
groups: string[];
|
|
60
|
+
groups: string[]; // Lamaste groups (Gatekeeper tier), not raw Authelia groups
|
|
61
61
|
status: 'active' | 'disabled';
|
|
62
|
-
canSignIn: boolean;
|
|
62
|
+
canSignIn: boolean; // false = directory-only person (see "People who never sign in")
|
|
63
63
|
updatedAt: string;
|
|
64
|
-
version: number;
|
|
64
|
+
version: number; // per-record, increments on every change
|
|
65
65
|
}
|
|
66
66
|
```
|
|
67
67
|
|
|
@@ -75,9 +75,9 @@ An **entitlement** says a user may use a plugin, optionally with roles:
|
|
|
75
75
|
|
|
76
76
|
```ts
|
|
77
77
|
interface Entitlement {
|
|
78
|
-
plugin: string;
|
|
78
|
+
plugin: string; // "pdks", "apsiyon", …
|
|
79
79
|
userId: string;
|
|
80
|
-
roles: string[];
|
|
80
|
+
roles: string[]; // plugin-declared roles, e.g. ["viewer"], ["manager"]
|
|
81
81
|
source: 'direct' | `group:${string}`;
|
|
82
82
|
}
|
|
83
83
|
```
|
|
@@ -111,9 +111,9 @@ only the declared attributes and the plugin's roles.
|
|
|
111
111
|
interface AudienceMember {
|
|
112
112
|
userId: string;
|
|
113
113
|
username: string;
|
|
114
|
-
displayName?: string;
|
|
115
|
-
email?: string;
|
|
116
|
-
roles: string[];
|
|
114
|
+
displayName?: string; // only if declared
|
|
115
|
+
email?: string; // only if declared
|
|
116
|
+
roles: string[]; // this plugin's roles only
|
|
117
117
|
status: 'active' | 'disabled';
|
|
118
118
|
version: number;
|
|
119
119
|
}
|
|
@@ -178,7 +178,7 @@ and compares it with the local projection (by `userId` and `version`). It
|
|
|
178
178
|
applies differences and logs how many it found — a non-zero count on a
|
|
179
179
|
healthy system is a bug in the change feed and is reported to the panel.
|
|
180
180
|
|
|
181
|
-
## SDK (`@lamalibre/lamaste-identity@4.
|
|
181
|
+
## SDK (`@lamalibre/lamaste-identity@4.3.0`)
|
|
182
182
|
|
|
183
183
|
Today's surface stays; three pieces are added.
|
|
184
184
|
|
|
@@ -187,9 +187,10 @@ Today's surface stays; three pieces are added.
|
|
|
187
187
|
```ts
|
|
188
188
|
const subscriber = new IdentitySubscriber({
|
|
189
189
|
plugin: 'pdks',
|
|
190
|
-
client,
|
|
191
|
-
cursorStore,
|
|
192
|
-
apply: async (changes, tx) => {
|
|
190
|
+
client, // existing IdentityClient (mTLS)
|
|
191
|
+
cursorStore, // where the subscriber keeps { directoryId, seq }
|
|
192
|
+
apply: async (changes, tx) => {
|
|
193
|
+
// the plugin decides what to do with each change
|
|
193
194
|
for (const c of changes) {
|
|
194
195
|
if (c.kind === 'upsert') upsertPerson(tx, c.member);
|
|
195
196
|
else markRemoved(tx, c.userId, c.reason);
|
|
@@ -197,8 +198,8 @@ const subscriber = new IdentitySubscriber({
|
|
|
197
198
|
},
|
|
198
199
|
reconcileEvery: '24h',
|
|
199
200
|
});
|
|
200
|
-
await subscriber.start();
|
|
201
|
-
subscriber.notify(seq);
|
|
201
|
+
await subscriber.start(); // initial snapshot or catch-up, then waits for notify()
|
|
202
|
+
subscriber.notify(seq); // called by the plugin's /admin/identity/notify route
|
|
202
203
|
```
|
|
203
204
|
|
|
204
205
|
Guarantees:
|
|
@@ -217,8 +218,8 @@ Requests reach applications with a **signed identity assertion** instead of
|
|
|
217
218
|
bare `Remote-*` headers:
|
|
218
219
|
|
|
219
220
|
- **Through the app-plugin forwarder:** the server half adds the caller to
|
|
220
|
-
the caller assertion it already signs (app-plugin design,
|
|
221
|
-
between the
|
|
221
|
+
the caller assertion it already signs (app-plugin design, _Authentication
|
|
222
|
+
between the halves_).
|
|
222
223
|
- **Through a plain tunnel** (`authenticated` / `restricted`): Gatekeeper,
|
|
223
224
|
already the `auth_request` target, returns
|
|
224
225
|
`X-Lamalibre-Identity: <JWT>` on allow; nginx copies it to the upstream
|
|
@@ -272,11 +273,11 @@ entitlement to end one thing).
|
|
|
272
273
|
A user can hold several **credentials**, each of which proves "this is that
|
|
273
274
|
user" in a different place:
|
|
274
275
|
|
|
275
|
-
| Credential
|
|
276
|
-
|
|
277
|
-
| Password + TOTP
|
|
278
|
-
| Badges (card ids)
|
|
279
|
-
| Registry / API tokens | Terminals, machines
|
|
276
|
+
| Credential | Where it is presented | Verified by |
|
|
277
|
+
| --------------------- | ----------------------------------------- | ----------------------------------------- |
|
|
278
|
+
| Password + TOTP | Browser (Authelia) | Authelia |
|
|
279
|
+
| Badges (card ids) | Card readers at kiosks, the portal, doors | The site agent, from its local projection |
|
|
280
|
+
| Registry / API tokens | Terminals, machines | The service that issued them (e.g. Feria) |
|
|
280
281
|
|
|
281
282
|
Badges are managed in Lamaste on the user's page: enrol (scan or type the
|
|
282
283
|
id), label (e.g. "13.56 MHz", "125 kHz"), revoke. A person may hold several —
|
|
@@ -315,13 +316,13 @@ card read ─► site agent: badge id → userId (local projection)
|
|
|
315
316
|
"One action ends everything" is only true once the change reaches each
|
|
316
317
|
place that enforces it:
|
|
317
318
|
|
|
318
|
-
| Enforcer
|
|
319
|
-
|
|
320
|
-
| Authelia (web sign-in)
|
|
321
|
-
| Tunnelled web apps
|
|
322
|
-
| Agent-hosted app plugins
|
|
323
|
-
| Site agents (badges, doors) | Notify, else next 30 s sync
|
|
324
|
-
| GitLab
|
|
319
|
+
| Enforcer | Reached by | Typical latency |
|
|
320
|
+
| --------------------------- | ---------------------------------- | ------------------------------------------------ |
|
|
321
|
+
| Authelia (web sign-in) | Lamaste writes it directly | immediate |
|
|
322
|
+
| Tunnelled web apps | Gatekeeper, per request | immediate (within its cache lifetime) |
|
|
323
|
+
| Agent-hosted app plugins | Notify through the internal tunnel | seconds |
|
|
324
|
+
| Site agents (badges, doors) | Notify, else next 30 s sync | seconds; **unbounded while the site is offline** |
|
|
325
|
+
| GitLab | Connector (below) | seconds |
|
|
325
326
|
|
|
326
327
|
Offline sites are the hard case. A badge decision taken from a projection
|
|
327
328
|
that has not heard about a revocation will allow a dismissed employee in.
|
|
@@ -373,7 +374,7 @@ HR system — each is a subscriber with its own projection and its own idea of
|
|
|
373
374
|
"block".
|
|
374
375
|
|
|
375
376
|
**Feria** is one too. Its design (`feria/docs/design/networked-registry-and-login.md`)
|
|
376
|
-
asks Lamaste for a
|
|
377
|
+
asks Lamaste for a _group-change hook_ that revokes or downgrades a person's
|
|
377
378
|
registry tokens when their `feria-*` membership changes. In this model that
|
|
378
379
|
hook is Feria's identity subscription: Feria declares the roles `reader`,
|
|
379
380
|
`publisher` and `admin`, entitlements grant them, and a `remove` or a role
|
|
@@ -412,24 +413,24 @@ directory and one out of it.
|
|
|
412
413
|
|
|
413
414
|
## Lamaste changes required
|
|
414
415
|
|
|
415
|
-
| #
|
|
416
|
-
|
|
417
|
-
| 1
|
|
418
|
-
| 2
|
|
419
|
-
| 3
|
|
420
|
-
| 4
|
|
421
|
-
| 5
|
|
422
|
-
| 6
|
|
423
|
-
| 7
|
|
424
|
-
| 8
|
|
425
|
-
| 9
|
|
426
|
-
| 10
|
|
427
|
-
| 11
|
|
428
|
-
| 12
|
|
416
|
+
| # | Change |
|
|
417
|
+
| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
418
|
+
| 1 | Directory store in SQLite with `userId`, versions, `seq` triggers, `directoryId`; `users.yml` becomes derived. Migration assigns ids to existing users. |
|
|
419
|
+
| 2 | One entitlement model: migrate `user-plugin-access.json` into Gatekeeper grants with roles. |
|
|
420
|
+
| 3 | `identity` block in the plugin manifest (roles, attributes). |
|
|
421
|
+
| 4 | Audience snapshot and change-feed endpoints, scoped per plugin. |
|
|
422
|
+
| 5 | Notification fan-out: app-plugin forwarder, in-process event, `seq` in agent sync responses. |
|
|
423
|
+
| 6 | Identity assertions: signing key, JWKS endpoint, Gatekeeper returns the assertion, nginx forwards it. |
|
|
424
|
+
| 7 | Bulk user import (CSV) and a directory import API for external systems of record. |
|
|
425
|
+
| 8 | SDK: `IdentitySubscriber`, `verifyIdentity` plugin, SQLite projection helpers. |
|
|
426
|
+
| 9 | Badges as user credentials: enrol, label, revoke; `badges` attribute for card-reading plugins. |
|
|
427
|
+
| 10 | Audit log: events forwarded by plugins and agents (`userId`, credential, action, result). |
|
|
428
|
+
| 11 | Projection age reported by agents; offline policy declared by badge-reading plugins. |
|
|
429
|
+
| 12 | Authelia OIDC provider (shared with Feria) and a GitLab connector plugin. |
|
|
429
430
|
|
|
430
431
|
## Open questions
|
|
431
432
|
|
|
432
|
-
1.
|
|
433
|
+
1. _(Decided 2026-10-13: employees are Lamaste users; badges are credentials on the user.)_
|
|
433
434
|
2. **PDKS's source of truth:** samplepark pushes into Lamaste, or Lamaste
|
|
434
435
|
mirrors samplepark?
|
|
435
436
|
3. **Erasure:** which plugins hold data that must be anonymised on request,
|
package/vendor/docs/package.json
CHANGED
|
@@ -29,7 +29,7 @@ feria dev registry — OUT OF SCOPE, do not touch
|
|
|
29
29
|
|
|
30
30
|
### Naming Rules
|
|
31
31
|
|
|
32
|
-
- **`lamaste`** is the core lib. You `import { ... } from '@lamalibre/lamaste@4.
|
|
32
|
+
- **`lamaste`** is the core lib. You `import { ... } from '@lamalibre/lamaste@4.3.0'`. No `-lib` suffix.
|
|
33
33
|
- **`-d` suffix** for daemons — Unix convention (`httpd`, `sshd`, `mongod`). Instantly signals "long-running process".
|
|
34
34
|
- **`-ui`** for React component libraries — universal term, avoids "serverd serves the panel" tautology.
|
|
35
35
|
- **`create-*`** for all npx one-shot tools — the one npm convention everyone knows.
|
|
@@ -74,24 +74,24 @@ lamaste core library (types, constants, schemas, pl
|
|
|
74
74
|
|
|
75
75
|
| # | Package (npm name) | Type | Depends on | Purpose |
|
|
76
76
|
| --- | ----------------------------------- | ----------- | ---------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
77
|
-
| 1 | `@lamalibre/lamaste@4.
|
|
78
|
-
| | | | | Subpath: `@lamalibre/lamaste@4.
|
|
79
|
-
| | | | | Subpath: `@lamalibre/lamaste@4.
|
|
80
|
-
| 2 | `@lamalibre/lamaste-agent@4.
|
|
81
|
-
| 3 | `@lamalibre/lamaste-agentd@4.
|
|
82
|
-
| 4 | `@lamalibre/lamaste-agent-ui@4.
|
|
83
|
-
| 5 | `@lamalibre/lamaste-server@4.
|
|
84
|
-
| 6 | `@lamalibre/lamaste-serverd@4.
|
|
85
|
-
| 7 | `@lamalibre/lamaste-server-ui@4.
|
|
86
|
-
| 8 | `@lamalibre/lamaste@4.
|
|
87
|
-
| 9 | `@lamalibre/lamaste-cloud@4.
|
|
88
|
-
| 10 | `@lamalibre/lamaste-tickets@4.
|
|
89
|
-
| 11 | `@lamalibre/lamaste-identity@4.
|
|
90
|
-
| 12 | `@lamalibre/create-lamaste@4.
|
|
91
|
-
| 13 | `@lamalibre/create-lamaste-agent@4.
|
|
92
|
-
| 14 | `@lamalibre/create-lamaste-desktop@4.
|
|
93
|
-
| 15 | `@lamalibre/create-lamaste-admin@4.
|
|
94
|
-
| 16 | `@lamalibre/create-lamaste-e2e@4.
|
|
77
|
+
| 1 | `@lamalibre/lamaste@4.3.0` | core lib | nothing | Types, constants, Zod schemas, plugin host Fastify plugin, atomic file helpers, client interfaces |
|
|
78
|
+
| | | | | Subpath: `@lamalibre/lamaste@4.3.0/agent` — agent domain logic |
|
|
79
|
+
| | | | | Subpath: `@lamalibre/lamaste@4.3.0/server` — server domain logic |
|
|
80
|
+
| 2 | `@lamalibre/lamaste-agent@4.3.0` | CLI | `lamaste` | Thin agent CLI. No Fastify, no HTTP |
|
|
81
|
+
| 3 | `@lamalibre/lamaste-agentd@4.3.0` | daemon | `lamaste` | Agent REST API on :9393. No CLI argument parsing |
|
|
82
|
+
| 4 | `@lamalibre/lamaste-agent-ui@4.3.0` | UI lib | `lamaste` | Agent React components + browser SPA build. Used by desktop and agentd |
|
|
83
|
+
| 5 | `@lamalibre/lamaste-server@4.3.0` | CLI | `lamaste` | **NEW.** Thin server CLI. No Fastify, no HTTP |
|
|
84
|
+
| 6 | `@lamalibre/lamaste-serverd@4.3.0` | daemon | `lamaste` | Server REST API on :3100. No CLI argument parsing. Renamed from `serverd` |
|
|
85
|
+
| 7 | `@lamalibre/lamaste-server-ui@4.3.0` | UI lib | `lamaste` | Server/admin React components + browser SPA build. Replaces both `panel-client` and `lamaste-admin-panel` |
|
|
86
|
+
| 8 | `@lamalibre/lamaste@4.3.0-desktop` | desktop | `lamaste` | Unified Tauri app. Multi-target: full, agent-only, server-only. Credentials, tray, deep links |
|
|
87
|
+
| 9 | `@lamalibre/lamaste-cloud@4.3.0` | lib + CLI | — | Cloud provider abstraction (already correct pattern) |
|
|
88
|
+
| 10 | `@lamalibre/lamaste-tickets@4.3.0` | SDK | — | Agent-to-agent authorization |
|
|
89
|
+
| 11 | `@lamalibre/lamaste-identity@4.3.0` | SDK | — | Authelia identity parsing and query |
|
|
90
|
+
| 12 | `@lamalibre/create-lamaste@4.3.0` | provisioner | `lamaste` | Server provisioner: OS hardening, nginx, Authelia, certs. `npx create-lamaste` |
|
|
91
|
+
| 13 | `@lamalibre/create-lamaste-agent@4.3.0` | provisioner | `lamaste` | Agent provisioner: cert enrollment, service setup. `npx create-lamaste-agent`. Renamed from `install-lamaste-agent` |
|
|
92
|
+
| 14 | `@lamalibre/create-lamaste-desktop@4.3.0` | installer | — | Desktop app installer. `npx create-lamaste-desktop`. Renamed from `install-lamaste-desktop` |
|
|
93
|
+
| 15 | `@lamalibre/create-lamaste-admin@4.3.0` | provisioner | `lamaste` | Admin cert upgrade to hardware-bound. `npx create-lamaste-admin`. Renamed from `install-lamaste-admin` |
|
|
94
|
+
| 16 | `@lamalibre/create-lamaste-e2e@4.3.0` | test infra | — | E2E test MCP server. `npx create-lamaste-e2e`. Renamed from `install-lamaste-e2e-mcp` |
|
|
95
95
|
| 17 | `@lamalibre/feria` | dev tool | — | Dev registry + release runner. **Out of scope — do not touch in this refactor** |
|
|
96
96
|
|
|
97
97
|
### Rename Map (1.x → 2.0.0)
|
|
@@ -116,7 +116,7 @@ The core library uses **subpath exports** to provide domain-specific entry point
|
|
|
116
116
|
|
|
117
117
|
```json
|
|
118
118
|
{
|
|
119
|
-
"name": "@lamalibre/lamaste@4.
|
|
119
|
+
"name": "@lamalibre/lamaste@4.3.0",
|
|
120
120
|
"exports": {
|
|
121
121
|
".": "./dist/index.js",
|
|
122
122
|
"./agent": "./dist/agent/index.js",
|
|
@@ -126,9 +126,9 @@ The core library uses **subpath exports** to provide domain-specific entry point
|
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
```typescript
|
|
129
|
-
import { RESERVED_API_PREFIXES, pluginManifestSchema } from '@lamalibre/lamaste@4.
|
|
130
|
-
import { loadRegistry, loadAgent, isAgentLoaded } from '@lamalibre/lamaste@4.
|
|
131
|
-
import { createTunnel, rotateCert } from '@lamalibre/lamaste@4.
|
|
129
|
+
import { RESERVED_API_PREFIXES, pluginManifestSchema } from '@lamalibre/lamaste@4.3.0';
|
|
130
|
+
import { loadRegistry, loadAgent, isAgentLoaded } from '@lamalibre/lamaste@4.3.0/agent';
|
|
131
|
+
import { createTunnel, rotateCert } from '@lamalibre/lamaste@4.3.0/server';
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
**Why subpath exports instead of three packages (`lamaste-lib`, `lamaste-lib-agent`, `lamaste-lib-server`):**
|
|
@@ -149,7 +149,7 @@ import { createTunnel, rotateCert } from '@lamalibre/lamaste@4.2.0/server';
|
|
|
149
149
|
|
|
150
150
|
| Layer | Agent side | Server side |
|
|
151
151
|
| ------------------------ | ----------------------------------------------- | ---------------------------------------------- |
|
|
152
|
-
| **Domain logic** | `@lamalibre/lamaste@4.
|
|
152
|
+
| **Domain logic** | `@lamalibre/lamaste@4.3.0/agent` | `@lamalibre/lamaste@4.3.0/server` |
|
|
153
153
|
| **Operational CLI** | `lamaste-agent` | `lamaste-server` (new) |
|
|
154
154
|
| **Long-running daemon** | `lamalibre-lamaste-agentd` on :9393 (extracted) | `lamalibre-lamaste-serverd` on :3100 (renamed) |
|
|
155
155
|
| **UI components** | `lamaste-agent-ui` (renamed) | `lamaste-server-ui` (merged) |
|
|
@@ -471,7 +471,7 @@ The Rust backend has both `commands.rs` (legacy) and `agents.rs` (multi-agent).
|
|
|
471
471
|
|
|
472
472
|
Create `packages/lamaste/` (TypeScript) with subpath exports:
|
|
473
473
|
|
|
474
|
-
**Root (`@lamalibre/lamaste@4.
|
|
474
|
+
**Root (`@lamalibre/lamaste@4.3.0`):**
|
|
475
475
|
|
|
476
476
|
- Types: `AdminClient`, `AgentClient` TypeScript interfaces, plugin manifest types, capability types
|
|
477
477
|
- Constants: Reserved API prefixes, curated plugin list, capability names
|
|
@@ -479,7 +479,7 @@ Create `packages/lamaste/` (TypeScript) with subpath exports:
|
|
|
479
479
|
- Plugin Host: Fastify plugin for plugin route mounting, bundle serving, disabled handler (unified from three routers)
|
|
480
480
|
- File Helpers: Atomic write (temp → fsync → rename), promise-chain mutex
|
|
481
481
|
|
|
482
|
-
**Agent subpath (`@lamalibre/lamaste@4.
|
|
482
|
+
**Agent subpath (`@lamalibre/lamaste@4.3.0/agent`):**
|
|
483
483
|
|
|
484
484
|
- Platform: Path helpers, platform detection (from `platform.js`)
|
|
485
485
|
- Registry: Agent registry CRUD, label validation, legacy migration (from `registry.js`)
|
|
@@ -491,7 +491,7 @@ Create `packages/lamaste/` (TypeScript) with subpath exports:
|
|
|
491
491
|
- Server Registry: servers.json and storage-servers.json CRUD (new — from Rust `cloud.rs`)
|
|
492
492
|
- Mode: Server mode and admin cert file operations (new — from Rust `mode.rs`)
|
|
493
493
|
|
|
494
|
-
**Server subpath (`@lamalibre/lamaste@4.
|
|
494
|
+
**Server subpath (`@lamalibre/lamaste@4.3.0/server`):**
|
|
495
495
|
|
|
496
496
|
- Plugins: Server-side plugin lifecycle (uses shared schema from root)
|
|
497
497
|
- Tunnels: Tunnel creation workflow with rollback (from `routes/tunnels.js`)
|