docs: correct host-access authorization model description

README.md and docs/architecture.md described authorization as a client-side
loop over each of a user's LDAP groups, calling the SSO's
GET /api/discovery/resources?group=<cn> once per group. The actual code
(utils/access.js, accessibleHosts()) makes a single call to the SSO's
GET /api/discovery/access/:uid, which resolves the user's groups
server-side and returns the full access projection in one response.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0113gCdnfSCuZr6xvPDxTo3D
This commit is contained in:
2026-08-06 21:27:31 -04:00
parent 57d0600fc0
commit 24a6a718e0
9 changed files with 17 additions and 11 deletions
+7 -5
View File
@@ -41,11 +41,13 @@ Every attempt — success or failure, with method and reason — is audited.
## 2. Access & target resolution
The hosts a user may reach are computed from the directory, not a local list:
1. The user's LDAP group memberships (`(&(objectClass=groupOfNames)(member=…))`).
2. For each group, the SSO's
`GET /api/discovery/resources?group=<cn>` (authenticated with an API token),
unioned and filtered to `kind: host`.
the jump host calls the SSO's `GET /api/discovery/access/:uid` (authenticated
with an API token) once per user; the SSO evaluates the user's LDAP group
memberships server-side and returns the full access projection in one
response, already filtered to `kind: host`. (The jump host also has an
admin-only `allHosts()` path, used for the unfiltered catalog listing, which
does call `GET /api/discovery/resources?group=<cn>` per group — but that's
not the per-user authorization path.)
Each host's dial address is `metadata.ip` (or the hostname from
`metadata.address`) and port `metadata.sshPort` (default 22). Results are cached