Skip to content

Commit 4bba810

Browse files
authored
docs(agentos): align cloud deployment auth docs (#14325) (#14376)
1 parent f4329e4 commit 4bba810

3 files changed

Lines changed: 85 additions & 10 deletions

File tree

learn/agentos/cloud-deployment/Configuration.md

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,18 @@ A deployment's `config.mjs` is gitignored and copied from `config.template.mjs`.
4545
| `transport` | `'stdio'` | `'stdio'` (local single-repo) or `'sse'` (StreamableHTTP — a cloud deployment serving remote tenants). |
4646
| `mcpHttpPort` | `3000` | The port the SSE transport listens on (only when `transport === 'sse'`). |
4747
| `publicUrl` | `null` | Canonical public URL — required behind a reverse proxy for OAuth 2.1 / OIDC audience claims + SSE callback advertising. |
48-
| `auth` | OIDC block | OAuth 2.1 / OIDC config (`host`, `port`, `realm`, `issuerUrl`, `clientId`, `clientSecret`, `trustProxyIdentity`) — used only when `transport === 'sse'`. |
48+
| `auth.mode` | `'oidc'` | Server-side bearer strategy for HTTP/SSE: `'oidc'` uses OIDC introspection + audience enforcement; `'gitlab-pat'` validates a GitLab OAuth token or PAT against `/api/v4/user` and returns a bare bearer challenge on failure. |
49+
| `auth.issuerUrl` / `auth.host` / `auth.realm` | `null` / `null` / `'master'` | OIDC authority inputs for the default server mode. `issuerUrl` is preferred when the provider publishes discovery metadata directly. |
50+
| `auth.clientId` / `auth.clientSecret` | `null` / `''` | OIDC introspection client credentials for deployments that require them. |
51+
| `auth.trustProxyIdentity` | `false` | Accept identity from a trusted reverse-proxy header after the ingress strips spoofable client-supplied headers. |
52+
| `auth.gitlabApiBaseUrl` | `'https://gitlab.com'` | GitLab API root used only by `auth.mode === 'gitlab-pat'`; set to a self-managed GitLab host when needed. |
53+
| `auth.allowedClientIds` / `auth.allowedUsers` | `[]` / `[]` | Optional hardening gates for GitLab bearer mode. Empty means any token that resolves to a valid GitLab user is accepted. |
54+
55+
Compose healthchecks use `ai/scripts/diagnostics/mcpHealthcheck.mjs` against the
56+
same `/mcp` route as external callers. When a deployment sets
57+
`NEO_AUTH_MODE=gitlab-pat`, also set `NEO_MCP_HEALTHCHECK_TOKEN` (or
58+
`NEO_MCP_HEALTHCHECK_TOKEN_ENV`) to a GitLab bearer with `read_user`; otherwise
59+
the server can answer correctly while Compose keeps it unhealthy.
4960

5061
Each key is also bindable via an environment variable (`NEO_KB_DEFAULT_TENANT_ID`, `NEO_TRANSPORT`, `MCP_HTTP_PORT`, …) — see `config.template.mjs`'s `envBindings` map for the full set.
5162

@@ -57,12 +68,14 @@ Each key is also bindable via an environment variable (`NEO_KB_DEFAULT_TENANT_ID
5768
|---|---|---|
5869
| `NEO_KB_MCP_URL` | Yes unless `--url` is passed | Remote KB MCP endpoint URL, for example `https://agent-os.example.com/kb/mcp`. |
5970
| `NEO_KB_MCP_TRANSPORT` | No | MCP client transport; defaults to `streamable-http`, accepts `sse` for older endpoint wiring. |
60-
| `NEO_KB_INGEST_TOKEN` | Yes for production | Bearer token for the repo-push automation identity. |
71+
| `NEO_KB_INGEST_TOKEN` | Yes for production | Bearer token for the repo-push automation identity. In OIDC mode it is an access token whose audience matches the KB public URL; in GitLab bearer mode it is a GitLab OAuth access token or PAT accepted by `/api/v4/user`. |
6172
| `NEO_KB_TOKEN_ENV` | No | Name of the environment variable that holds the bearer token when the deployment does not use `NEO_KB_INGEST_TOKEN`. |
6273
| `NEO_KB_TENANT_ID` | No | Envelope default for tenant id; authenticated server context remains authoritative. |
6374
| `NEO_KB_REPO_SLUG` | No | Envelope default for repo slug; use a deterministic, secret-free value such as `neomjs/create-app`. |
6475

65-
The token is a KB MCP authorization credential, not a Git credential. Store it in the tenant hook/CI secret store and rotate it using the deployment's normal OIDC or workload-identity policy.
76+
The token is a KB MCP authorization credential, not a Git credential. Store it
77+
in the tenant hook/CI secret store and rotate it using the deployment's normal
78+
OIDC, GitLab OAuth, or PAT-rotation policy.
6679

6780
## Per-tenant config storage — `KnowledgeBaseTenantConfig` (#11637)
6881

@@ -105,7 +118,26 @@ The default-resolved tier means a single-repo deployment needs no tenant config
105118

106119
## Model-provider runtime + orchestrator-readiness
107120

108-
Beyond KB ingestion, a cloud deployment tunes the model-provider request behaviour and the orchestrator's provider-readiness probe through five env vars. All carry resident-friendly defaults — a zero-config deployment keeps local models warm across REM/Sandman cycles and probes patiently on cold start.
121+
Beyond KB ingestion, a cloud deployment chooses where model calls run. External
122+
provider endpoints remain the default operational posture; the optional
123+
`local-model` compose profile is a self-hosted OpenAI-compatible provider that
124+
operators opt into explicitly.
125+
126+
### Provider selection
127+
128+
| Variable | Default | Meaning |
129+
|---|---|---|
130+
| `NEO_MODEL_PROVIDER` | `openAiCompatible` | Chat / summary / dream provider selector for Memory Core and the Orchestrator. Set `gemini` for the cloud API route. |
131+
| `NEO_EMBEDDING_PROVIDER` | `openAiCompatible` | Embedding provider selector for Knowledge Base and Memory Core. Set `gemini` for cloud embeddings. |
132+
| `NEO_OPENAI_COMPATIBLE_HOST` | deployment-specific | Base URL for a local or hosted OpenAI-compatible endpoint, for example `http://local-model:11434` when the compose profile is enabled. |
133+
| `NEO_OPENAI_COMPATIBLE_MODEL` | deployment-specific | Chat model id already resident or pullable on the selected OpenAI-compatible provider. |
134+
| `NEO_OPENAI_COMPATIBLE_EMBEDDING_MODEL` | deployment-specific | Embedding model id for the same provider; local deployments must keep chat + embedding roles available together. |
135+
| `NEO_OPENAI_COMPATIBLE_API_KEY` | optional | Bearer token for OpenAI-compatible providers that require one; normally empty for the internal `local-model` service. |
136+
137+
The request behaviour and orchestrator-readiness probe below carry
138+
resident-friendly defaults — when a local provider profile is selected, Neo keeps
139+
the configured chat and embedding roles warm across REM/Sandman cycles and
140+
probes patiently on cold start.
109141

110142
### Provider request `keep_alive`
111143

learn/agentos/cloud-deployment/Security.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,37 @@ This asymmetry drives retention policy (see Phase 4 #11628): KB backup is cost-o
5252

5353
## Auth flow and tenant context
5454

55-
The authenticated-ingestion-context resolution maps a tenant's push to its `tenantId` / `originAgentIdentity` before the ingestion service reaches Chroma. The invariant that holds regardless of the transport: **the tenant tuple is server-derived from the authenticated identity, never trusted from the payload.** Endpoint-exact auth wiring depends on the deployment's proxy/OIDC mode; see [Deployment Cookbook](../DeploymentCookbook.md) for the MCP deployment boundary and [Hook Wiring](./HookWiring.md) for ingestion facades.
55+
The authenticated-ingestion-context resolution maps a tenant's push to its
56+
`tenantId` / `originAgentIdentity` before the ingestion service reaches Chroma.
57+
The invariant that holds regardless of the transport: **the tenant tuple is
58+
server-derived from the authenticated identity, never trusted from the
59+
payload.**
60+
61+
The shipped HTTP/SSE deployment has three identity shapes:
62+
63+
- **OIDC server mode** (`NEO_AUTH_MODE=oidc`, the default) validates
64+
`Authorization: Bearer <token>` through the configured issuer, enforces the
65+
MCP server's `NEO_PUBLIC_URL` as the token audience, and derives identity from
66+
`preferred_username` / `sub`.
67+
- **GitLab bearer mode** (`NEO_AUTH_MODE=gitlab-pat`) accepts a GitLab OAuth
68+
access token or Personal Access Token as the bearer, validates it against
69+
GitLab's `/api/v4/user`, and derives identity from the returned username. This
70+
mode intentionally has no OIDC audience claim or protected-resource metadata;
71+
failed requests return a bare `WWW-Authenticate: Bearer` challenge.
72+
- **Trusted proxy identity** (`NEO_AUTH_TRUST_PROXY_IDENTITY=true`) lets an
73+
authenticated reverse proxy inject `X-Preferred-Username` /
74+
`X-Auth-Request-Preferred-Username`. The reference Caddy ingress strips any
75+
client-supplied copies before an optional auth layer injects trusted values.
76+
77+
In `gitlab-pat` mode, the container healthchecks hit the same authenticated
78+
`/mcp` route as external callers. Set `NEO_MCP_HEALTHCHECK_TOKEN` to a bearer
79+
that validates under the selected mode, or the MCP server can be healthy but
80+
Compose will still mark the service unhealthy.
81+
82+
Endpoint-exact auth wiring depends on the deployment's chosen mode; see
83+
[Client Authentication](./ClientAuthentication.md),
84+
[Deployment Cookbook](../DeploymentCookbook.md), and [Hook Wiring](./HookWiring.md)
85+
for the operator and ingestion facades.
5686

5787
## Post-MVP hardening review (#11736)
5888

@@ -64,7 +94,7 @@ tree and which remain deferred to tracked residual work.
6494

6595
| Hardening area | Current documented baseline | Disposition |
6696
|---|---|---|
67-
| Reverse proxy identity boundary | `ai/deploy/Caddyfile` strips spoofable identity headers before optional auth injection, and [Deployment Cookbook](../DeploymentCookbook.md) Section 4 names the same invariant. | Actioned for the reference ingress. Production deployments must enable an OIDC/proxy-auth layer or direct OIDC before serving mutually-untrusting tenants. |
97+
| Reverse proxy identity boundary | `ai/deploy/Caddyfile` strips spoofable identity headers before optional auth injection, and [Deployment Cookbook](../DeploymentCookbook.md) Section 4 names the same invariant. | Actioned for the reference ingress. Production deployments must enable OIDC server mode, GitLab bearer mode, or trusted proxy identity before serving mutually-untrusting tenants. |
6898
| Repo-push automation token | [Tenant Ingestion Model](./TenantIngestionModel.md) and [Hook Wiring](./HookWiring.md) define `NEO_KB_INGEST_TOKEN` as a tenant-scoped MCP authorization credential, never a Git credential and never part of `repoSlug`, logs, manifests, or graph-visible config. | Actioned for the push-based MVP path. Server-side Git credential transport remains deferred to [#11731](https://github.com/neomjs/neo/issues/11731). |
6999
| Secret storage | The guide tree consistently routes tokens through tenant hook/CI secret stores and deployment auth/provider config, not committed files. | Actioned at runbook level. Platform-specific secret-manager/KMS wiring belongs to downstream deployment-pipeline work ([#11733](https://github.com/neomjs/neo/issues/11733)) once a concrete platform is selected. |
70100
| Network policy | The reference compose profile keeps KB and MC internal behind Caddy (`expose`, public path routing through `/kb/*` and `/mc/*`). | Actioned for compose. Kubernetes network policies, managed ingress rules, and service-mesh variants are deferred platform work, tracked under [#11733](https://github.com/neomjs/neo/issues/11733) if adopted. |

learn/agentos/cloud-deployment/TenantIngestionModel.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,28 @@ If a future server-side clone path becomes necessary, [#11731](https://github.co
8484

8585
## Repo-Push Automation Identity
8686

87-
For day-0 tenant push, create a machine/service account in the deployment's OIDC provider and scope it to the tenant repository source it represents. The tenant hook or CI job stores the resulting access token in its secret store and exposes it as `NEO_KB_INGEST_TOKEN`.
87+
For day-0 tenant push, create an automation identity accepted by the deployment's
88+
MCP auth mode and scope it to the tenant repository source it represents. The
89+
tenant hook or CI job stores the resulting bearer in its secret store and
90+
exposes it as `NEO_KB_INGEST_TOKEN`.
8891

89-
The deployment's OAuth audience/resource must match the KB MCP public resource. Behind the reference ingress, the client URL is typically:
92+
For OIDC server mode, the deployment's OAuth audience/resource must match the
93+
KB MCP public resource. Behind the reference ingress, the KB MCP URL is
94+
typically:
9095

9196
```text
9297
https://agent-os.example.com/kb/mcp
9398
```
9499

95-
The token's resource should match the canonical KB public URL configured by `NEO_PUBLIC_URL` / the auth provider. The exact token acquisition flow is operator-owned — client credentials, workload identity, or CI OIDC exchange are all valid — but the resulting token must be short-lived or rotated, tenant-scoped, and stored outside the repository.
100+
In the default OIDC server mode, the token's resource should match the canonical
101+
KB public URL configured by `NEO_PUBLIC_URL` / the auth provider. In
102+
`NEO_AUTH_MODE=gitlab-pat`, the bearer is a GitLab OAuth access token or
103+
Personal Access Token with `read_user`; the server validates it against
104+
GitLab's `/api/v4/user` and derives the tenant identity from the returned
105+
username. The exact token acquisition flow is operator-owned — client
106+
credentials, workload identity, GitLab OAuth, or a rotated PAT are all valid —
107+
but the resulting bearer must be tenant-scoped, stored outside the repository,
108+
and rotated according to the deployment's auth policy.
96109

97110
The server remains authoritative for tenant identity. `NEO_KB_TENANT_ID` is a client default for envelope construction; authenticated context still stamps or rejects tenant metadata according to deployment policy.
98111

@@ -151,7 +164,7 @@ Incremental pushes should include deletion intent. Prefer this default shape:
151164
2. Build the source-family inventory.
152165
3. Choose dispatch for each family: raw server parse, registered server parser, client-side `parsed-chunk-v1`, unsupported, or excluded.
153166
4. Run initial import with `ai:ingest-tenant` when volume exceeds the MCP gate.
154-
5. Create the repo-push automation identity, configure token audience/resource, and store the token as `NEO_KB_INGEST_TOKEN` in the tenant hook or CI secret store.
167+
5. Create the repo-push automation identity, configure the OIDC audience or GitLab bearer policy, and store the token as `NEO_KB_INGEST_TOKEN` in the tenant hook or CI secret store.
155168
6. Wire incremental `pre-push` or CI pushes through `ai:kb-push-client` to the remote MCP endpoint.
156169
7. Include tombstones and revision boundaries; include manifests at reconciliation points.
157170
8. Fail the hook or CI job on structured ingestion errors instead of silently dropping files.

0 commit comments

Comments
 (0)