Skip to content

Commit d42db71

Browse files
authored
docs(auth): restructure auth docs into Fern navigation and fix rendering issues (#368)
Add the Access Control section to the Fern docs navigation (latest.yml), covering authentication, authorization, deployment, and security model pages. Fix permissions-reference table rendering by replacing escaped pipe characters (`\\|`) with HTML entities (`&#124;`) and `<code>` tags so permission patterns display correctly in MDX. Update cross-document links from relative `.md` paths to absolute Fern URL paths. Improve roles-and-permissions with a Mermaid flowchart for the role hierarchy. Refactor security-model and concepts pages for clarity and accuracy. Add docs-watch.mjs, a file-system watcher that triggers Fern live-reload when any file outside `docs/fern/` changes, and wire it up as `make docs-watch`. Extend auth-tools.py with a `generate-docs` command that regenerates the permissions reference from the auth configuration. Signed-off-by: Ryan Sadler <267728323+ironcommit@users.noreply.github.com>
1 parent 8709272 commit d42db71

14 files changed

Lines changed: 326 additions & 140 deletions

File tree

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ docs-deps: ## Install the Fern docs tooling (docs/fern node deps)
110110
docs: ## Start the Fern docs dev server (local preview, prints a localhost URL)
111111
cd docs/fern && npm run dev
112112

113+
.PHONY: docs-watch
114+
docs-watch: ## Start Fern docs dev plus a repo-level watcher for docs/** changes
115+
cd docs/fern && npm run watch
116+
113117
.PHONY: docs-check
114118
docs-check: ## Validate the Fern docs (fern check + validate-mdx + gated-link check)
115119
cd docs/fern && npm run check

docs/AGENTS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ Run these from the repo root (they wrap `cd docs/fern && npm run …`):
1010
|---|---|
1111
| `make docs-deps` | Install docs tooling (first run on a machine) |
1212
| `make docs` | Local dev server (live preview) |
13+
| `make docs-watch` | Local dev server plus repo-level watcher for `docs/**` changes outside `docs/fern/` |
1314
| `make docs-check` | `fern check` + MDX validation + gated-link check (what CI runs) |
1415
| `make docs-broken-links` | Report broken links |
1516
| `make docs-fix-links` | Auto-delink references into gated pages |
1617

1718
Local preview and the published site read the **same** `docs/fern/versions/latest.yml`, so what you see locally is what ships.
1819

20+
Use `make docs` when you are only editing `docs/fern/` config. Use `make docs-watch` when you are editing page content elsewhere under `docs/`, since it restarts the Fern dev server when repo-level docs files change outside `docs/fern/`.
21+
1922
## Rules that bite if you miss them
2023

2124
- **Navigation is the build.** Fern only builds pages listed in `docs/fern/versions/latest.yml`. A `.mdx` not in the nav is **not built** (404, not indexed) — that is how unready features are gated. Do **not** use `hidden: true` for gating (it still builds/serves the page).

docs/auth/authorization/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Add users to workspaces, assign roles, manage members.
3838
Token-level scope model and two-layer authorization.
3939

4040
</Card>
41-
<Card title="Permissions Reference" href="/documentation/reference/authorization/permissions-reference">
41+
<Card title="Permissions Reference" href="/documentation/access-control/authorization/permissions-reference">
4242

4343
Complete list of all permissions with role assignments.
4444

docs/auth/authorization/permissions-reference.mdx

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
title: "Permissions Reference"
33
description: ""
44
---
5-
(permissions-reference)=
65

6+
{/* This page is generated from the auth configuration. Regenerate it with `uv run python services/core/auth/scripts/auth-tools.py generate-docs`. */}
77

8-
Complete reference of all permissions across the NeMo Platform APIs. Each permission controls access to a specific operation within an individual API. Permissions are assigned to users through [roles](roles-and-permissions.md).
8+
Complete reference of all permissions across the NeMo Platform APIs. Each permission controls access to a specific operation within an individual API. Permissions are assigned to users through [roles](/documentation/access-control/authorization/roles-and-permissions).
99

10-
For token-level access restrictions, see [API Scopes](api-scopes.md). For the RBAC model, see [Authorization Concepts](../concepts.md).
10+
For token-level access restrictions, see [API Scopes](/documentation/access-control/authorization/api-scopes). For the RBAC model, see [Authorization Concepts](/documentation/access-control/concepts).
1111

1212
<Note>
1313

@@ -18,79 +18,79 @@ PlatformAdmin is omitted — it bypasses permission checks entirely at the polic
1818

1919
| Permission | Description | Viewer | Editor | Admin |
2020
|------------|-------------|:------:|:------:|:-----:|
21-
| `entities.(read \\| create \\| update \\| delete)` | Read, create, update, delete entities | | | |
21+
| <code>entities.(read &#124; create &#124; update &#124; delete)</code> | Read, create, update, delete entities | | | |
2222

2323
## Files API
2424

2525
| Permission | Description | Viewer | Editor | Admin |
2626
|------------|-------------|:------:|:------:|:-----:|
27-
| `filesets.(read \\| list)` | Read, list files ||||
28-
| `filesets.(create \\| update \\| delete)` | Create, update, delete files | |||
27+
| <code>filesets.(read &#124; list)</code> | Read, list files ||||
28+
| <code>filesets.(create &#124; update &#124; delete)</code> | Create, update, delete files | |||
2929

3030
## Guardrails API
3131

3232
| Permission | Description | Viewer | Editor | Admin |
3333
|------------|-------------|:------:|:------:|:-----:|
3434
| `guardrails.checks.exec` | Execute guardrail checks | |||
35-
| `guardrails.configs.(read \\| list)` | Read, list guardrails configs ||||
36-
| `guardrails.configs.(create \\| update \\| delete)` | Create, update, delete guardrails configs | |||
35+
| <code>guardrails.configs.(read &#124; list)</code> | Read, list guardrails configs ||||
36+
| <code>guardrails.configs.(create &#124; update &#124; delete)</code> | Create, update, delete guardrails configs | |||
3737

3838
## IAM API
3939

4040
| Permission | Description | Viewer | Editor | Admin |
4141
|------------|-------------|:------:|:------:|:-----:|
42-
| `iam.(read \\| list \\| create \\| delete)` | Read, list, create, delete iam | | ||
42+
| <code>iam.(read &#124; list &#124; create &#124; delete)</code> | Read, list, create, delete iam | | ||
4343
| `iam.bundle.read` | Download OPA authorization bundle (external OPA / advanced ops) | | | |
4444

4545
## Inference API
4646

4747
| Permission | Description | Viewer | Editor | Admin |
4848
|------------|-------------|:------:|:------:|:-----:|
49-
| `inference.deployment-configs.(read \\| list)` | Read, list inference deployment-configs ||||
50-
| `inference.deployment-configs.(create \\| delete)` | Create, delete inference deployment-configs | |||
51-
| `inference.deployments.(read \\| list)` | Read, list inference deployments ||||
52-
| `inference.deployments.(create \\| update \\| delete)` | Create, update, delete inference deployments | |||
49+
| <code>inference.deployment-configs.(read &#124; list)</code> | Read, list inference deployment-configs ||||
50+
| <code>inference.deployment-configs.(create &#124; delete)</code> | Create, delete inference deployment-configs | |||
51+
| <code>inference.deployments.(read &#124; list)</code> | Read, list inference deployments ||||
52+
| <code>inference.deployments.(create &#124; update &#124; delete)</code> | Create, update, delete inference deployments | |||
5353
| `inference.gateway.model.exec` | Execute model gateway inference ||||
5454
| `inference.gateway.openai.exec` | Execute OpenAI-compatible gateway inference ||||
5555
| `inference.gateway.provider.exec` | Execute provider gateway inference ||||
56-
| `inference.providers.(read \\| list)` | Read, list inference providers ||||
57-
| `inference.providers.(create \\| update \\| delete)` | Create, update, delete inference providers | |||
58-
| `inference.virtual-models.(read \\| list)` | Read, list inference virtual-models ||||
59-
| `inference.virtual-models.(create \\| update \\| delete)` | Create, update, delete inference virtual-models | |||
56+
| <code>inference.providers.(read &#124; list)</code> | Read, list inference providers ||||
57+
| <code>inference.providers.(create &#124; update &#124; delete)</code> | Create, update, delete inference providers | |||
58+
| <code>inference.virtual-models.(read &#124; list)</code> | Read, list inference virtual-models ||||
59+
| <code>inference.virtual-models.(create &#124; update &#124; delete)</code> | Create, update, delete inference virtual-models | |||
6060

6161
## Intake API
6262

6363
| Permission | Description | Viewer | Editor | Admin |
6464
|------------|-------------|:------:|:------:|:-----:|
65-
| `intake.annotations.(read \\| list)` | Read, list intake annotations ||||
66-
| `intake.annotations.(create \\| delete)` | Create, delete intake annotations | |||
67-
| `intake.evaluator-results.(read \\| list)` | Read, list intake evaluator-results ||||
65+
| <code>intake.annotations.(read &#124; list)</code> | Read, list intake annotations ||||
66+
| <code>intake.annotations.(create &#124; delete)</code> | Create, delete intake annotations | |||
67+
| <code>intake.evaluator-results.(read &#124; list)</code> | Read, list intake evaluator-results ||||
6868
| `intake.evaluator-results.create` | Create intake evaluator results | |||
6969
| `intake.experiment-groups.read` | Read intake experiment groups ||||
70-
| `intake.experiment-groups.(create \\| update \\| delete)` | Create, update, delete intake experiment-groups | |||
70+
| <code>intake.experiment-groups.(create &#124; update &#124; delete)</code> | Create, update, delete intake experiment-groups | |||
7171
| `intake.experiments.read` | Read intake experiments ||||
72-
| `intake.experiments.(create \\| update \\| delete)` | Create, update, delete intake experiments | |||
72+
| <code>intake.experiments.(create &#124; update &#124; delete)</code> | Create, update, delete intake experiments | |||
7373
| `intake.ingest.create` | Ingest traces into intake | |||
74-
| `intake.spans.(read \\| list)` | Read, list intake spans ||||
74+
| <code>intake.spans.(read &#124; list)</code> | Read, list intake spans ||||
7575
| `intake.traces.read` | Read intake traces ||||
7676

7777
## Jobs API
7878

7979
| Permission | Description | Viewer | Editor | Admin |
8080
|------------|-------------|:------:|:------:|:-----:|
81-
| `jobs.(read \\| list)` | Read, list jobs ||||
82-
| `jobs.(create \\| update \\| delete \\| cancel)` | Create, update, delete, cancel jobs | |||
81+
| <code>jobs.(read &#124; list)</code> | Read, list jobs ||||
82+
| <code>jobs.(create &#124; update &#124; delete &#124; cancel)</code> | Create, update, delete, cancel jobs | |||
8383

8484
## Models API
8585

8686
| Permission | Description | Viewer | Editor | Admin |
8787
|------------|-------------|:------:|:------:|:-----:|
88-
| `models.(read \\| list)` | Read, list models ||||
89-
| `models.(create \\| update \\| delete)` | Create, update, delete models | |||
90-
| `models.adapters.(read \\| list)` | Read, list models adapters ||||
91-
| `models.adapters.(create \\| update \\| delete)` | Create, update, delete models adapters | |||
88+
| <code>models.(read &#124; list)</code> | Read, list models ||||
89+
| <code>models.(create &#124; update &#124; delete)</code> | Create, update, delete models | |||
90+
| <code>models.adapters.(read &#124; list)</code> | Read, list models adapters ||||
91+
| <code>models.adapters.(create &#124; update &#124; delete)</code> | Create, update, delete models adapters | |||
9292
| `models.prompts.read` | Read model prompts ||||
93-
| `models.prompts.(create \\| update \\| delete)` | Create, update, delete models prompts | |||
93+
| <code>models.prompts.(create &#124; update &#124; delete)</code> | Create, update, delete models prompts | |||
9494
| `models.prompts.list` | List model prompts | | | |
9595
| `models.tool-call-plugin.set` | Whether this user can set tool_call_plugin on Models or Deployment Configs *(policy-enforced)* | | ||
9696
| `models.trust-remote-code.set` | Whether this user can set trust_remote_code on Models *(policy-enforced)* | | ||
@@ -105,35 +105,35 @@ PlatformAdmin is omitted — it bypasses permission checks entirely at the polic
105105

106106
| Permission | Description | Viewer | Editor | Admin |
107107
|------------|-------------|:------:|:------:|:-----:|
108-
| `projects.(read \\| list)` | Read, list projects ||||
109-
| `projects.(create \\| update \\| delete)` | Create, update, delete projects | |||
108+
| <code>projects.(read &#124; list)</code> | Read, list projects ||||
109+
| <code>projects.(create &#124; update &#124; delete)</code> | Create, update, delete projects | |||
110110

111111
## Safe Synthesizer API
112112

113113
| Permission | Description | Viewer | Editor | Admin |
114114
|------------|-------------|:------:|:------:|:-----:|
115-
| `safe-synthesizer.jobs.(read \\| list \\| create \\| delete \\| cancel)` | Read, list, create, delete, cancel safe synthesizer jobs | | | |
115+
| <code>safe-synthesizer.jobs.(read &#124; list &#124; create &#124; delete &#124; cancel)</code> | Read, list, create, delete, cancel safe synthesizer jobs | | | |
116116

117117
## Secrets API
118118

119119
| Permission | Description | Viewer | Editor | Admin |
120120
|------------|-------------|:------:|:------:|:-----:|
121-
| `secrets.(read \\| list)` | Read, list secrets ||||
122-
| `secrets.(create \\| update \\| delete)` | Create, update, delete secrets | |||
123-
| `secrets.(access \\| rotate)` | Access, rotate secrets | | | |
121+
| <code>secrets.(read &#124; list)</code> | Read, list secrets ||||
122+
| <code>secrets.(create &#124; update &#124; delete)</code> | Create, update, delete secrets | |||
123+
| <code>secrets.(access &#124; rotate)</code> | Access, rotate secrets | | | |
124124

125125
## Workspaces API
126126

127127
| Permission | Description | Viewer | Editor | Admin |
128128
|------------|-------------|:------:|:------:|:-----:|
129-
| `workspaces.(read \\| list)` | Read, list workspaces ||||
130-
| `workspaces.(update \\| delete)` | Update, delete workspaces | |||
131-
| `workspaces.members.(list \\| create \\| update \\| delete)` | List, create, update, delete workspaces members | | ||
129+
| <code>workspaces.(read &#124; list)</code> | Read, list workspaces ||||
130+
| <code>workspaces.(update &#124; delete)</code> | Update, delete workspaces | |||
131+
| <code>workspaces.members.(list &#124; create &#124; update &#124; delete)</code> | List, create, update, delete workspaces members | | ||
132132
| `workspaces.members.read` | Read workspace member details | | | |
133133

134134
## Related
135135

136-
- [Roles & Permissions](roles-and-permissions.md) — Role descriptions and hierarchy.
137-
- [API Scopes](api-scopes.md) — Token-level scope restrictions.
138-
- [Authorization Concepts](../concepts.md) — Workspaces, roles, bindings, and the RBAC model.
139-
- [Security Model](../security-model.md) — Trust boundaries and authorization layers.
136+
- [Roles & Permissions](/documentation/access-control/authorization/roles-and-permissions) — Role descriptions and hierarchy.
137+
- [API Scopes](/documentation/access-control/authorization/api-scopes) — Token-level scope restrictions.
138+
- [Authorization Concepts](/documentation/access-control/concepts) — Workspaces, roles, bindings, and the RBAC model.
139+
- [Security Model](/documentation/access-control/security-model) — Trust boundaries and authorization layers.

docs/auth/authorization/roles-and-permissions.mdx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,32 @@ NeMo Platform provides four predefined roles, each designed for a specific user
4141

4242
Each role includes all permissions of the roles below it:
4343

44-
```text
45-
PlatformAdmin
46-
47-
Admin (+manage_members, +change_visibility)
48-
49-
Editor (+create, +update, +delete, +cancel)
50-
51-
Viewer (list, read, inference)
44+
```mermaid
45+
flowchart BT
46+
Viewer["Viewer
47+
+list
48+
+read
49+
+inference"]
50+
Editor["Editor
51+
+create
52+
+update
53+
+delete
54+
+cancel"]
55+
Admin["Admin
56+
+manage members
57+
+change visibility"]
58+
PlatformAdmin["PlatformAdmin
59+
all workspaces
60+
all operations"]
61+
62+
Viewer --> Editor
63+
Editor --> Admin
64+
Admin --> PlatformAdmin
5265
```
5366

5467
## Permission Matrix
5568

56-
Rows are operations; columns are roles. A checkmark indicates the role has permission.
69+
Rows are operations; columns are roles. Read the hierarchy above first: each role inherits everything below it, and the tables call out the points where additional privileges appear.
5770

5871
### Workspace Operations
5972

docs/auth/concepts.mdx

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,16 @@ Workspaces can have different access levels based on role bindings:
3333

3434
Each principal can have different roles in different workspaces:
3535

36-
```text
37-
alice@company.com:
38-
- Admin in workspace "team-ml"
39-
- Editor in workspace "shared-datasets"
40-
- Viewer in workspace "prod-models"
36+
```mermaid
37+
flowchart TB
38+
Alice["alice@company.com"]
39+
TeamML["team-ml<br/>Admin"]
40+
Shared["shared-datasets<br/>Editor"]
41+
Prod["prod-models<br/>Viewer"]
42+
43+
Alice --> TeamML
44+
Alice --> Shared
45+
Alice --> Prod
4146
```
4247

4348
### Wildcard Principal
@@ -46,10 +51,14 @@ The special principal `*` (asterisk) represents **all authenticated users**. Gra
4651

4752
This is the mechanism for creating shared workspaces:
4853

49-
```text
50-
Workspace: "shared-datasets"
51-
├── Role Binding: principal="*", role="Viewer" # Everyone can read
52-
└── Role Binding: principal="alice@company.com", role="Admin" # Alice manages
54+
```mermaid
55+
flowchart TB
56+
Workspace["Workspace: shared-datasets"]
57+
Everyone["Role Binding<br/>principal=*<br/>role=Viewer"]
58+
AliceAdmin["Role Binding<br/>principal=alice@company.com<br/>role=Admin"]
59+
60+
Workspace --> Everyone
61+
Workspace --> AliceAdmin
5362
```
5463

5564
When both a wildcard binding and an explicit binding exist for a user, the highest role wins.
@@ -60,14 +69,16 @@ When both a wildcard binding and an explicit binding exist for a user, the highe
6069

6170
The predefined roles form a hierarchy — each role includes all permissions of the roles below it:
6271

63-
```text
64-
PlatformAdmin (all operations across all workspaces)
65-
66-
Admin (+ manage members, change visibility)
67-
68-
Editor (+ create, update, delete resources)
69-
70-
Viewer (list, read, run inference)
72+
```mermaid
73+
flowchart BT
74+
Viewer["Viewer<br/>list, read, run inference"]
75+
Editor["Editor<br/>create, update, delete resources"]
76+
Admin["Admin<br/>manage members, change visibility"]
77+
PlatformAdmin["PlatformAdmin<br/>all operations across all workspaces"]
78+
79+
Viewer --> Editor
80+
Editor --> Admin
81+
Admin --> PlatformAdmin
7182
```
7283

7384
Custom roles can be defined at deployment time with arbitrary permission sets — they do not need to follow this hierarchy. For the complete permission matrix, see [Roles & Permissions](/documentation/access-control/authorization/roles-and-permissions).
@@ -118,19 +129,16 @@ A role binding contains:
118129
- **Workspace**: The workspace where access is granted (e.g., `team-ml`)
119130
- **Role**: The role being assigned (e.g., `Editor`)
120131

121-
```text
122-
Workspace: "team-ml-research"
123-
├── Role Binding 1
124-
│ ├── Principal: "alice@company.com"
125-
│ └── Role: "Admin"
126-
127-
├── Role Binding 2
128-
│ ├── Principal: "bob@company.com"
129-
│ └── Role: "Editor"
130-
131-
└── Role Binding 3
132-
├── Principal: "charlie@company.com"
133-
└── Role: "Viewer"
132+
```mermaid
133+
flowchart TB
134+
WorkspaceRB["Workspace: team-ml-research"]
135+
RB1["Role Binding 1<br/>alice@company.com<br/>Admin"]
136+
RB2["Role Binding 2<br/>bob@company.com<br/>Editor"]
137+
RB3["Role Binding 3<br/>charlie@company.com<br/>Viewer"]
138+
139+
WorkspaceRB --> RB1
140+
WorkspaceRB --> RB2
141+
WorkspaceRB --> RB3
134142
```
135143

136144
## Automatic Role Assignment

docs/auth/deployment/configuration.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ auth:
3737
admin_email: "your-admin@company.com"
3838
```
3939

40-
For a complete reference of all `auth` fields and their defaults, see the [platform configuration reference](/documentation/reference/configuration-reference). Auth-related values are found under `platformConfig.auth` in the values file.
40+
This page covers the auth-specific configuration fields you need to enable and operate authorization. Auth-related values are found under `platformConfig.auth` in the values file.
4141

4242
For OIDC-specific fields (`auth.oidc`), see [OIDC Setup](/documentation/access-control/authentication/oidc-setup).
4343

0 commit comments

Comments
 (0)