@biaoo/tiangong-wiki 0.2.2 → 0.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.
@@ -0,0 +1,482 @@
1
+ # Centralized Service Deployment
2
+
3
+ Single-host deployment guide for running Tiangong Wiki as a centralized service with:
4
+
5
+ - a local daemon (`tiangong-wiki daemon run`)
6
+ - a local MCP adapter (`mcp-server/dist/index.js`)
7
+ - an Nginx reverse proxy handling TLS, static Bearer tokens, and trusted actor headers
8
+
9
+ This guide is the V1 baseline for issue `#040`. It assumes Linux + `systemd` and intentionally does not cover HA, load balancing, or cloud-vendor-specific templates.
10
+
11
+ ---
12
+
13
+ ## Topology
14
+
15
+ ```text
16
+ Remote MCP client
17
+ -> HTTPS /mcp (Nginx)
18
+ -> local MCP service (127.0.0.1:9400)
19
+ -> local daemon (127.0.0.1:8787)
20
+ -> pages/ + index.db + templates/ + audit.ndjson + local Git repo
21
+ ```
22
+
23
+ Rules for V1:
24
+
25
+ - Do not expose the daemon directly to the public internet.
26
+ - Only the reverse proxy should terminate TLS and validate Bearer tokens.
27
+ - The proxy must overwrite actor headers before traffic reaches MCP.
28
+ - MCP stays a thin adapter and must not write files directly.
29
+
30
+ ---
31
+
32
+ ## Directory Layout
33
+
34
+ Recommended server layout:
35
+
36
+ ```text
37
+ /srv/tiangong-wiki/
38
+ ├── current/ # checked-out tiangong-wiki repo + built artifacts
39
+ ├── workspace/
40
+ │ ├── pages/
41
+ │ ├── templates/
42
+ │ ├── wiki.config.json
43
+ │ ├── index.db
44
+ │ └── .queue-artifacts/
45
+ ├── vault/
46
+ └── .wiki-runtime/
47
+ └── audit.ndjson
48
+
49
+ /etc/tiangong-wiki/
50
+ └── centralized.env
51
+
52
+ /etc/systemd/system/
53
+ ├── tiangong-wiki-daemon.service
54
+ └── tiangong-wiki-mcp.service
55
+ ```
56
+
57
+ Recommended ownership:
58
+
59
+ - application repo: `root:root`
60
+ - runtime workspace and vault: `tiangong-wiki:tiangong-wiki`
61
+ - `systemd` services run as `tiangong-wiki`
62
+
63
+ ---
64
+
65
+ ## Build and Bootstrap
66
+
67
+ ```bash
68
+ git clone <repo-url> /srv/tiangong-wiki/current
69
+ cd /srv/tiangong-wiki/current
70
+ npm ci
71
+ npm run build
72
+ ```
73
+
74
+ Initialize the workspace once:
75
+
76
+ ```bash
77
+ mkdir -p /srv/tiangong-wiki/workspace/pages
78
+ mkdir -p /srv/tiangong-wiki/workspace/templates
79
+ mkdir -p /srv/tiangong-wiki/vault
80
+
81
+ cat >/etc/tiangong-wiki/centralized.env <<'EOF'
82
+ WIKI_PATH=/srv/tiangong-wiki/workspace/pages
83
+ WIKI_DB_PATH=/srv/tiangong-wiki/workspace/index.db
84
+ WIKI_CONFIG_PATH=/srv/tiangong-wiki/workspace/wiki.config.json
85
+ WIKI_TEMPLATES_PATH=/srv/tiangong-wiki/workspace/templates
86
+ VAULT_PATH=/srv/tiangong-wiki/vault
87
+
88
+ WIKI_SYNC_INTERVAL=300
89
+ WIKI_DAEMON_PORT=8787
90
+
91
+ WIKI_MCP_HOST=127.0.0.1
92
+ WIKI_MCP_PORT=9400
93
+ WIKI_MCP_PATH=/mcp
94
+ WIKI_DAEMON_BASE_URL=http://127.0.0.1:8787
95
+
96
+ WIKI_GIT_AUTO_PUSH=true
97
+ WIKI_GIT_PUSH_REMOTE=origin
98
+ WIKI_GIT_PUSH_DELAY_MS=3000
99
+ EOF
100
+
101
+ cd /srv/tiangong-wiki/current
102
+ env $(grep -v '^#' /etc/tiangong-wiki/centralized.env | xargs) node dist/index.js init
103
+ ```
104
+
105
+ An example env file is also provided at [references/examples/centralized-service/centralized.env.example](./examples/centralized-service/centralized.env.example).
106
+
107
+ Important:
108
+
109
+ - Bearer tokens are not part of `centralized.env`
110
+ - Bearer token validation belongs to Nginx, not the daemon or MCP process
111
+ - Keep real tokens in a private Nginx include file such as `/etc/nginx/snippets/wiki-auth-tokens.conf`
112
+
113
+ ---
114
+
115
+ ## Required Environment Variables
116
+
117
+ ### Core runtime
118
+
119
+ - `WIKI_PATH`
120
+ - `WIKI_DB_PATH`
121
+ - `WIKI_CONFIG_PATH`
122
+ - `WIKI_TEMPLATES_PATH`
123
+ - `VAULT_PATH`
124
+ - `WIKI_SYNC_INTERVAL`
125
+
126
+ ### Daemon
127
+
128
+ - `WIKI_DAEMON_PORT`
129
+
130
+ Notes:
131
+
132
+ - the daemon bind host is currently fixed to `127.0.0.1`
133
+ - the daemon should stay loopback-only in production
134
+
135
+ ### MCP adapter
136
+
137
+ - `WIKI_MCP_HOST`
138
+ - `WIKI_MCP_PORT`
139
+ - `WIKI_MCP_PATH`
140
+ - `WIKI_DAEMON_BASE_URL`
141
+
142
+ Recommended values:
143
+
144
+ - `WIKI_MCP_HOST=127.0.0.1`
145
+ - `WIKI_MCP_PORT=9400`
146
+ - `WIKI_MCP_PATH=/mcp`
147
+ - `WIKI_DAEMON_BASE_URL=http://127.0.0.1:8787`
148
+
149
+ ### Optional Git push batching
150
+
151
+ - `WIKI_GIT_AUTO_PUSH=true|false`
152
+ - `WIKI_GIT_PUSH_REMOTE`
153
+ - `WIKI_GIT_PUSH_DELAY_MS`
154
+
155
+ V1 decision:
156
+
157
+ - local Git commit is part of the write transaction
158
+ - async push batching stays inside the daemon process
159
+ - external cron is not required for the primary path
160
+
161
+ ---
162
+
163
+ ## Git Repository Setup
164
+
165
+ The centralized service assumes the wiki workspace itself is a real Git repository.
166
+
167
+ Current behavior:
168
+
169
+ - every successful write attempts a local Git commit
170
+ - optional remote push is triggered asynchronously when `WIKI_GIT_AUTO_PUSH=true`
171
+ - push failure does not roll back a successful local write
172
+
173
+ Initialize the workspace repo:
174
+
175
+ ```bash
176
+ cd /srv/tiangong-wiki/workspace
177
+
178
+ git init -b main
179
+ git config user.name "tiangong-wiki"
180
+ git config user.email "tiangong-wiki@local"
181
+ ```
182
+
183
+ Notes:
184
+
185
+ - daemon-generated commits override author/committer identity from the write actor
186
+ - the local repo still should have basic Git config for operator workflows
187
+
188
+ Configure the GitHub remote:
189
+
190
+ ```bash
191
+ cd /srv/tiangong-wiki/workspace
192
+ git remote add origin git@github.com:YOUR_ORG/YOUR_REPO.git
193
+ git remote -v
194
+ ```
195
+
196
+ If the remote already exists:
197
+
198
+ ```bash
199
+ git remote set-url origin git@github.com:YOUR_ORG/YOUR_REPO.git
200
+ ```
201
+
202
+ Recommended authentication model:
203
+
204
+ - run the daemon as a dedicated system user such as `tiangong-wiki`
205
+ - give that user an SSH key dedicated to this deployment
206
+ - register the public key in GitHub as a deploy key, bot account key, or GitHub App-managed key
207
+
208
+ Example SSH bootstrap:
209
+
210
+ ```bash
211
+ sudo -u tiangong-wiki mkdir -p /home/tiangong-wiki/.ssh
212
+ sudo -u tiangong-wiki ssh-keygen -t ed25519 -f /home/tiangong-wiki/.ssh/id_ed25519 -N ""
213
+ sudo -u tiangong-wiki ssh-keyscan github.com >> /home/tiangong-wiki/.ssh/known_hosts
214
+ chmod 600 /home/tiangong-wiki/.ssh/known_hosts
215
+ ```
216
+
217
+ Do not store GitHub personal access tokens in `centralized.env`. Prefer SSH deploy keys.
218
+
219
+ Before enabling daemon-side auto push, verify Git access as the actual service user:
220
+
221
+ ```bash
222
+ sudo -u tiangong-wiki git -C /srv/tiangong-wiki/workspace status
223
+ sudo -u tiangong-wiki git -C /srv/tiangong-wiki/workspace remote -v
224
+ sudo -u tiangong-wiki git -C /srv/tiangong-wiki/workspace push origin HEAD
225
+ ```
226
+
227
+ If this manual push fails, daemon-side auto push will fail too.
228
+
229
+ Operational constraints:
230
+
231
+ - do not leave unrelated unstaged changes in the workspace repo
232
+ - ensure the target branch policy matches service behavior if you enable auto push
233
+ - if GitHub branch protection forbids direct push to the target branch, the current V1 service should push to an allowed branch or keep auto push disabled
234
+
235
+ ---
236
+
237
+ ## `systemd` Units
238
+
239
+ Example unit files are provided under [references/examples/centralized-service/](./examples/centralized-service/).
240
+
241
+ Install them:
242
+
243
+ ```bash
244
+ cp /srv/tiangong-wiki/current/references/examples/centralized-service/tiangong-wiki-daemon.service /etc/systemd/system/
245
+ cp /srv/tiangong-wiki/current/references/examples/centralized-service/tiangong-wiki-mcp.service /etc/systemd/system/
246
+
247
+ systemctl daemon-reload
248
+ systemctl enable --now tiangong-wiki-daemon
249
+ systemctl enable --now tiangong-wiki-mcp
250
+ ```
251
+
252
+ Startup order:
253
+
254
+ 1. Build the repo (`npm ci && npm run build`)
255
+ 2. Initialize the workspace (`node dist/index.js init`)
256
+ 3. Start `tiangong-wiki-daemon`
257
+ 4. Verify daemon health
258
+ 5. Start `tiangong-wiki-mcp`
259
+ 6. Verify MCP health
260
+ 7. Reload Nginx
261
+
262
+ ---
263
+
264
+ ## Nginx Reverse Proxy
265
+
266
+ V1 authentication model:
267
+
268
+ - Nginx validates a static Bearer token
269
+ - Nginx maps token -> actor identity
270
+ - Nginx injects:
271
+ - `X-Wiki-Actor-Id`
272
+ - `X-Wiki-Actor-Type`
273
+ - `X-Request-Id`
274
+ - MCP forwards these headers to the daemon on write requests
275
+
276
+ Important:
277
+
278
+ - never trust client-supplied actor headers directly
279
+ - always overwrite actor headers in the proxy
280
+ - clear `Authorization` before passing traffic upstream
281
+
282
+ Example config: [references/examples/centralized-service/nginx-centralized-wiki.conf](./examples/centralized-service/nginx-centralized-wiki.conf)
283
+
284
+ Recommended token placement:
285
+
286
+ 1. Create a private include file, for example `/etc/nginx/snippets/wiki-auth-tokens.conf`
287
+ 2. Move the `map $http_authorization ...` blocks into that file
288
+ 3. `include` that file from your main Nginx config inside the `http {}` scope
289
+ 4. Keep only placeholder tokens in repo-tracked example configs
290
+
291
+ This keeps static Bearer tokens out of the service env file and out of the checked-in site config.
292
+
293
+ Recommended exposure model:
294
+
295
+ - public: `/mcp` and `/mcp/health`
296
+ - private/admin only: daemon health and daemon HTTP routes
297
+
298
+ Because MCP uses streamable HTTP/SSE, keep:
299
+
300
+ - `proxy_http_version 1.1`
301
+ - `proxy_buffering off`
302
+ - generous read/send timeouts
303
+
304
+ ---
305
+
306
+ ## Health Checks
307
+
308
+ ### Local daemon
309
+
310
+ ```bash
311
+ curl http://127.0.0.1:8787/health
312
+ curl http://127.0.0.1:8787/status
313
+ curl http://127.0.0.1:8787/write-queue/summary
314
+ ```
315
+
316
+ ### Local MCP
317
+
318
+ ```bash
319
+ curl http://127.0.0.1:9400/health
320
+ ```
321
+
322
+ ### Through Nginx
323
+
324
+ ```bash
325
+ curl -H "Authorization: Bearer <token>" https://wiki.example.com/mcp/health
326
+ ```
327
+
328
+ ### `systemd`
329
+
330
+ ```bash
331
+ systemctl status tiangong-wiki-daemon
332
+ systemctl status tiangong-wiki-mcp
333
+
334
+ journalctl -u tiangong-wiki-daemon -f
335
+ journalctl -u tiangong-wiki-mcp -f
336
+ ```
337
+
338
+ ---
339
+
340
+ ## Runtime Contracts You Must Expect
341
+
342
+ These behaviors are intentional and should be documented to operators and MCP clients.
343
+
344
+ ### Revision conflicts
345
+
346
+ - daemon returns HTTP `409`
347
+ - MCP returns a structured tool error with `code=revision_conflict`
348
+ - callers must re-read the page and retry intentionally
349
+
350
+ ### Queue full
351
+
352
+ - daemon returns HTTP `503`
353
+ - cause: write queue depth exceeded the configured limit
354
+ - operators should inspect `/write-queue/summary`
355
+
356
+ ### Degraded Git commit failure
357
+
358
+ - the write may already be applied locally
359
+ - daemon returns a degraded error with `code=git_commit_failed`
360
+ - inspect `audit.ndjson`, local Git state, and journal output before retrying
361
+
362
+ ### Sync failure
363
+
364
+ - daemon does not commit to Git when sync fails
365
+ - audit log records `sync_failed`
366
+
367
+ ### Audit and journal locations
368
+
369
+ - audit log: `/srv/tiangong-wiki/.wiki-runtime/audit.ndjson` in the recommended layout
370
+ - Git journal: local repo commit history in `/srv/tiangong-wiki/workspace` or your chosen wiki root repo
371
+
372
+ ---
373
+
374
+ ## Backup and Push Strategy
375
+
376
+ V1 baseline:
377
+
378
+ - every successful write attempts a local Git commit
379
+ - optional async push is handled by the daemon when `WIKI_GIT_AUTO_PUSH=true`
380
+ - async push failure does not roll back the successful local write
381
+
382
+ Recommended operator practice:
383
+
384
+ - keep the workspace as a real Git repository with a configured `origin`
385
+ - snapshot both the workspace and `/etc/tiangong-wiki/centralized.env`
386
+ - monitor daemon logs for `git push failed`
387
+
388
+ Manual recovery after push failure:
389
+
390
+ ```bash
391
+ cd /srv/tiangong-wiki/workspace
392
+ git status
393
+ git log --oneline -n 5
394
+ git push origin HEAD
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Recovery Playbook
400
+
401
+ ### Daemon is down
402
+
403
+ ```bash
404
+ systemctl restart tiangong-wiki-daemon
405
+ curl http://127.0.0.1:8787/health
406
+ ```
407
+
408
+ If it still fails:
409
+
410
+ - inspect `journalctl -u tiangong-wiki-daemon -n 200`
411
+ - verify `index.db`, `wiki.config.json`, and Git repo status
412
+
413
+ ### MCP is down but daemon is healthy
414
+
415
+ ```bash
416
+ systemctl restart tiangong-wiki-mcp
417
+ curl http://127.0.0.1:9400/health
418
+ ```
419
+
420
+ Check:
421
+
422
+ - `WIKI_DAEMON_BASE_URL`
423
+ - `WIKI_MCP_PORT`
424
+ - Nginx upstream target
425
+
426
+ ### Queue remains full
427
+
428
+ Check:
429
+
430
+ ```bash
431
+ curl http://127.0.0.1:8787/write-queue/summary | jq
432
+ ```
433
+
434
+ Look for:
435
+
436
+ - a long-running active job
437
+ - repeated failing jobs
438
+ - vault queue pressure caused by large `sync --process` workloads
439
+
440
+ ### Revision conflict reported by clients
441
+
442
+ This is expected behavior, not an outage.
443
+
444
+ Action:
445
+
446
+ 1. re-read the page
447
+ 2. merge user intent with the latest revision
448
+ 3. retry with the new `ifRevision`
449
+
450
+ ### Degraded Git commit failure
451
+
452
+ Check:
453
+
454
+ ```bash
455
+ journalctl -u tiangong-wiki-daemon -n 200
456
+ tail -n 50 /srv/tiangong-wiki/.wiki-runtime/audit.ndjson
457
+ cd /srv/tiangong-wiki/workspace && git status
458
+ ```
459
+
460
+ Typical causes:
461
+
462
+ - workspace is not a Git repo
463
+ - Git identity or hooks are broken
464
+ - permissions do not allow commit creation
465
+
466
+ ### Actor metadata missing
467
+
468
+ If MCP returns `missing_actor`:
469
+
470
+ - verify Nginx is overwriting the three actor headers
471
+ - verify the client is calling the proxied `/mcp` endpoint, not the loopback service directly
472
+
473
+ ---
474
+
475
+ ## What V1 Does Not Cover
476
+
477
+ - multi-host deployments
478
+ - active/active daemon replicas
479
+ - cloud-specific Terraform or Helm modules
480
+ - alternate reverse proxy examples beyond Nginx
481
+
482
+ If those are needed later, treat them as follow-up work after the single-host contract is stable.
@@ -0,0 +1,25 @@
1
+ # Core workspace
2
+ WIKI_PATH=/srv/tiangong-wiki/workspace/pages
3
+ WIKI_DB_PATH=/srv/tiangong-wiki/workspace/index.db
4
+ WIKI_CONFIG_PATH=/srv/tiangong-wiki/workspace/wiki.config.json
5
+ WIKI_TEMPLATES_PATH=/srv/tiangong-wiki/workspace/templates
6
+ VAULT_PATH=/srv/tiangong-wiki/vault
7
+
8
+ # Daemon
9
+ WIKI_SYNC_INTERVAL=300
10
+ WIKI_DAEMON_PORT=8787
11
+
12
+ # MCP adapter
13
+ WIKI_MCP_HOST=127.0.0.1
14
+ WIKI_MCP_PORT=9400
15
+ WIKI_MCP_PATH=/mcp
16
+ WIKI_DAEMON_BASE_URL=http://127.0.0.1:8787
17
+
18
+ # Bearer tokens are NOT configured here.
19
+ # Put them in your reverse proxy config instead, for example:
20
+ # /etc/nginx/snippets/wiki-auth-tokens.conf
21
+
22
+ # Optional async Git push batching
23
+ WIKI_GIT_AUTO_PUSH=true
24
+ WIKI_GIT_PUSH_REMOTE=origin
25
+ WIKI_GIT_PUSH_DELAY_MS=3000
@@ -0,0 +1,68 @@
1
+ # Put the `map` blocks in the `http {}` scope.
2
+ # These token values are placeholders only.
3
+ # In production, move them to a private include such as:
4
+ # /etc/nginx/snippets/wiki-auth-tokens.conf
5
+
6
+ map $http_authorization $wiki_access_allowed {
7
+ default 0;
8
+ "Bearer codex-prod-token" 1;
9
+ "Bearer claude-prod-token" 1;
10
+ }
11
+
12
+ map $http_authorization $wiki_actor_id {
13
+ default "";
14
+ "Bearer codex-prod-token" "agent:codex";
15
+ "Bearer claude-prod-token" "agent:claude";
16
+ }
17
+
18
+ map $http_authorization $wiki_actor_type {
19
+ default "";
20
+ "Bearer codex-prod-token" "agent";
21
+ "Bearer claude-prod-token" "agent";
22
+ }
23
+
24
+ server {
25
+ listen 443 ssl http2;
26
+ server_name wiki.example.com;
27
+
28
+ ssl_certificate /etc/letsencrypt/live/wiki.example.com/fullchain.pem;
29
+ ssl_certificate_key /etc/letsencrypt/live/wiki.example.com/privkey.pem;
30
+
31
+ proxy_http_version 1.1;
32
+ proxy_buffering off;
33
+ proxy_read_timeout 360s;
34
+ proxy_send_timeout 360s;
35
+
36
+ location = /mcp/health {
37
+ if ($wiki_access_allowed = 0) { return 401; }
38
+
39
+ proxy_set_header Authorization "";
40
+ proxy_pass http://127.0.0.1:9400/health;
41
+ }
42
+
43
+ location /mcp {
44
+ if ($wiki_access_allowed = 0) { return 401; }
45
+
46
+ proxy_set_header Authorization "";
47
+ proxy_set_header X-Wiki-Actor-Id $wiki_actor_id;
48
+ proxy_set_header X-Wiki-Actor-Type $wiki_actor_type;
49
+ proxy_set_header X-Request-Id $request_id;
50
+
51
+ proxy_pass http://127.0.0.1:9400;
52
+ }
53
+
54
+ # Optional admin-only daemon routes.
55
+ # Keep them private or behind an internal allowlist / VPN.
56
+ location /daemon/ {
57
+ allow 127.0.0.1;
58
+ deny all;
59
+
60
+ proxy_set_header Authorization "";
61
+ proxy_set_header X-Wiki-Actor-Id "system:proxy-admin";
62
+ proxy_set_header X-Wiki-Actor-Type "system";
63
+ proxy_set_header X-Request-Id $request_id;
64
+
65
+ rewrite ^/daemon/(.*)$ /$1 break;
66
+ proxy_pass http://127.0.0.1:8787;
67
+ }
68
+ }
@@ -0,0 +1,17 @@
1
+ [Unit]
2
+ Description=Tiangong Wiki daemon
3
+ After=network-online.target
4
+ Wants=network-online.target
5
+
6
+ [Service]
7
+ Type=simple
8
+ User=tiangong-wiki
9
+ Group=tiangong-wiki
10
+ WorkingDirectory=/srv/tiangong-wiki/current
11
+ EnvironmentFile=/etc/tiangong-wiki/centralized.env
12
+ ExecStart=/usr/bin/env node /srv/tiangong-wiki/current/dist/index.js daemon run
13
+ Restart=always
14
+ RestartSec=5
15
+
16
+ [Install]
17
+ WantedBy=multi-user.target
@@ -0,0 +1,18 @@
1
+ [Unit]
2
+ Description=Tiangong Wiki MCP adapter
3
+ After=network-online.target tiangong-wiki-daemon.service
4
+ Wants=network-online.target
5
+ Requires=tiangong-wiki-daemon.service
6
+
7
+ [Service]
8
+ Type=simple
9
+ User=tiangong-wiki
10
+ Group=tiangong-wiki
11
+ WorkingDirectory=/srv/tiangong-wiki/current
12
+ EnvironmentFile=/etc/tiangong-wiki/centralized.env
13
+ ExecStart=/usr/bin/env node /srv/tiangong-wiki/current/mcp-server/dist/index.js
14
+ Restart=always
15
+ RestartSec=5
16
+
17
+ [Install]
18
+ WantedBy=multi-user.target
@@ -34,6 +34,21 @@ All configuration is managed through `.wiki.env` (created by `tiangong-wiki setu
34
34
  | `WIKI_TEMPLATES_PATH` | Yes | Path to the templates directory |
35
35
  | `WIKI_SYNC_INTERVAL` | No | Auto-sync interval in seconds (default: `86400`) |
36
36
 
37
+ ### Daemon and MCP
38
+
39
+ | Variable | Required | Description |
40
+ | --- | --- | --- |
41
+ | `WIKI_DAEMON_PORT` | No | Loopback daemon port |
42
+ | `WIKI_MCP_HOST` | No | MCP bind host (recommended: `127.0.0.1`) |
43
+ | `WIKI_MCP_PORT` | No | MCP bind port |
44
+ | `WIKI_MCP_PATH` | No | MCP HTTP path (default: `/mcp`) |
45
+ | `WIKI_DAEMON_BASE_URL` | For MCP service | Daemon base URL used by the MCP adapter |
46
+ | `WIKI_GIT_AUTO_PUSH` | No | Enable daemon-side async Git push batching |
47
+ | `WIKI_GIT_PUSH_REMOTE` | No | Git remote name for async push (default: `origin`) |
48
+ | `WIKI_GIT_PUSH_DELAY_MS` | No | Delay before async push (default: `3000`) |
49
+
50
+ For the full single-host deployment baseline, see [centralized-service-deployment.md](./centralized-service-deployment.md).
51
+
37
52
  ### Vault
38
53
 
39
54
  | Variable | Required | Description |
@@ -73,8 +88,11 @@ The agent uses [Codex SDK](https://www.npmjs.com/package/@openai/codex-sdk) to p
73
88
  | `WIKI_AGENT_API_KEY` | If enabled | API key for the LLM provider |
74
89
  | `WIKI_AGENT_MODEL` | No | Model name (e.g. `gpt-5.4`, `Qwen/Qwen3.5-397B-A17B-GPTQ-Int4`) |
75
90
  | `WIKI_AGENT_BATCH_SIZE` | No | Max concurrent vault items per batch (default: `5`) |
91
+ | `WIKI_AGENT_SANDBOX_MODE` | No | Codex sandbox mode: `danger-full-access` (default) or `workspace-write` |
76
92
  | `WIKI_PARSER_SKILLS` | No | Comma-separated parser skill list (e.g. `pdf,docx,pptx,xlsx`) |
77
93
 
94
+ `tiangong-wiki setup` now prompts for `WIKI_AGENT_SANDBOX_MODE` when automatic vault processing is enabled. The default is `danger-full-access`, and the setup wizard highlights that this mode grants full runtime access.
95
+
78
96
  ---
79
97
 
80
98
  ## Common Issues
@@ -102,6 +120,10 @@ Always run `tiangong-wiki lint --path <page-id> --format json` after mutations.
102
120
 
103
121
  Parser skills must be installed under `<workspace-root>/.agents/skills/`. Run `tiangong-wiki skill` to inspect installed skills. Use `tiangong-wiki skill update --all` to update.
104
122
 
123
+ ### Codex workflow sandbox fails to initialize
124
+
125
+ If the agent workflow fails with `bwrap`, `unshare`, `uid_map`, or similar sandbox startup errors, switch `WIKI_AGENT_SANDBOX_MODE` to `danger-full-access`. Use `workspace-write` only when you explicitly want that sandbox mode and know the host supports it.
126
+
105
127
  ---
106
128
 
107
129
  ## LLM Provider Setup