@yadsh/dsh-web-fetch-authenticated 0.2.0 → 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.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @yadsh/dsh-web-fetch-authenticated
2
2
 
3
+ [Русский гайд: настройка Jira и Confluence](docs/JIRA-CONFLUENCE.ru.md)
4
+
3
5
  An authenticated, policy-gated [`WebFetchProvider`](../../docs/) for the
4
6
  DeepSeek Harness web capability seam (`ctx.web`). It lets the existing
5
7
  model-facing `web_fetch(url)` tool retrieve content from approved
@@ -24,6 +26,7 @@ web_fetch(url)
24
26
  -> request with DNS pinning
25
27
  -> per-hop redirect re-validation
26
28
  -> bounded body read
29
+ -> content adapter (optional: REST fetch + normalization, see below)
27
30
  -> WebFetchResult (existing dsh-tool-web HTML -> Markdown)
28
31
  ```
29
32
 
@@ -79,6 +82,11 @@ Secrets are stored through the DSH credential store (`$DSH_HOME` credential
79
82
  backend) under POSIX-style reference names (`JIRA_TOKEN`); configuration keeps
80
83
  only the reference. Use the UI (or `api.credentials.set`) to store the value.
81
84
 
85
+ For an end-to-end corporate setup, including provider selection, credentials,
86
+ private-network policy, Jira/Confluence Cloud and Server/Data Center examples,
87
+ testing, and troubleshooting, see the
88
+ [Russian Jira and Confluence guide](docs/JIRA-CONFLUENCE.ru.md).
89
+
82
90
  ### Security defaults
83
91
 
84
92
  | Policy | Default |
@@ -95,6 +103,42 @@ answers are resolved, all candidates are classified, one denied answer denies
95
103
  the whole set (DNS-rebinding defense), and the socket is pinned to the
96
104
  approved addresses.
97
105
 
106
+ ## Content adapters (Jira / Confluence)
107
+
108
+ Raw HTML from enterprise apps converts to Markdown with all the application
109
+ chrome attached. A rule can instead select a **content adapter**: recognized
110
+ URLs are re-fetched from the product's REST API through the same authenticated
111
+ transport (same network policy, credentials, redirect policy, and limits) and
112
+ normalized into compact Markdown text — issue fields, description, and optional
113
+ comments/links for Jira; page metadata and the storage-format body for
114
+ Confluence. Unrecognized URLs fall back to raw HTTP/HTML.
115
+
116
+ - **Jira** — `/browse/ISSUE-KEY` at any deployment depth and `/issues/KEY`.
117
+ `jiraFlavor: server` (default) uses REST v2 and converts wiki-markup bodies;
118
+ `jiraFlavor: cloud` uses REST v3 and converts Atlassian Document Format.
119
+ `includeComments` and `includeLinks` add comments and issue links (off by
120
+ default).
121
+ - **Confluence** — `/pages/<id>/…` (Server and Cloud, including `/wiki/…`
122
+ paths) fetch directly; `/display/<SPACE>/<Title>` resolves via the title
123
+ lookup. Storage-format XHTML becomes Markdown: headings, lists, tables,
124
+ links, entities, code/noformat/panel/expand macros (unknown macros leave a
125
+ visible placeholder instead of vanishing).
126
+
127
+ Configured in the rule editor ("Content adapter") or declaratively:
128
+
129
+ ```yaml
130
+ adapter:
131
+ type: jira
132
+ jiraFlavor: server
133
+ includeComments: true
134
+ ```
135
+
136
+ Non-2xx REST responses stay results (the seam never throws for status codes):
137
+ the model sees a short `[Jira]`/`[Confluence]` HTTP-status note. Malformed or
138
+ non-JSON REST bodies fail with `AUTH_FETCH_ADAPTER_FAILED`. The generated text
139
+ is capped by the rule's `maxBodyChars`, and the connection tester runs the
140
+ adapter too, so Test shows the exact normalized text the model will get.
141
+
98
142
  ## Error codes
99
143
 
100
144
  `AUTH_FETCH_NO_MATCHING_RULE`, `AUTH_FETCH_AMBIGUOUS_MATCH`,
@@ -102,7 +146,8 @@ approved addresses.
102
146
  `AUTH_FETCH_CREDENTIAL_INVALID`, `AUTH_FETCH_NETWORK_DENIED`,
103
147
  `AUTH_FETCH_DNS_POLICY_DENIED`, `AUTH_FETCH_REDIRECT_DENIED`,
104
148
  `AUTH_FETCH_RESPONSE_TOO_LARGE`, `AUTH_FETCH_UNSUPPORTED_CONTENT`,
105
- `AUTH_FETCH_TIMEOUT`, `AUTH_FETCH_INVALID_URL`, `AUTH_FETCH_PROVIDER_ERROR` —
149
+ `AUTH_FETCH_TIMEOUT`, `AUTH_FETCH_INVALID_URL`, `AUTH_FETCH_PROVIDER_ERROR`,
150
+ `AUTH_FETCH_ADAPTER_FAILED` —
106
151
  surfaced as `WebError` codes through the existing `web_fetch` error metadata.
107
152
 
108
153
  ## Development
@@ -115,8 +160,8 @@ pnpm --filter @yadsh/dsh-web-fetch-authenticated check # lint + typecheck + te
115
160
  ```
116
161
 
117
162
  `INVESTIGATE.md` documents the exact DSH APIs and integration assumptions
118
- (SPEC phase 0). The v1 scope intentionally excludes cookies/OAuth/Jira-adapter
119
- features (see SPEC §29 phases 4–5).
163
+ (SPEC phase 0). Cookies/OAuth and advanced auth remain excluded (SPEC §29
164
+ phase 5); the Jira/Confluence content adapters (phase 4) are implemented.
120
165
 
121
166
  ## License
122
167
 
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "deepseekHarness": {
3
3
  "channel": "next",
4
- "range": ">=0.1.1-rc.2 <0.2.0",
4
+ "range": ">=0.1.5-rc.2 <0.2.0",
5
5
  "testedReleases": [
6
- "0.1.1-rc.2"
6
+ "0.1.5-rc.2"
7
7
  ],
8
8
  "requiredHostFeatures": [
9
9
  "web",
@@ -0,0 +1,406 @@
1
+ # Настройка `dsh-web-fetch-authenticated` для Jira и Confluence
2
+
3
+ Этот сценарий даёт модели доступ на чтение к конкретным задачам Jira и
4
+ страницам Confluence через обычный `web_fetch(url)`. Секрет остаётся на стороне
5
+ DSH Host: модель передаёт только URL, а плагин выбирает правило, проверяет
6
+ адрес назначения и добавляет авторизацию.
7
+
8
+ Гайд подходит для:
9
+
10
+ - Jira и Confluence Server/Data Center с PAT или локальной учётной записью,
11
+ для которой разрешён Basic auth;
12
+ - Jira и Confluence Cloud с API token;
13
+ - внутренних адресов в RFC1918/ULA-сетях;
14
+ - публичных корпоративных адресов с прямой API-авторизацией.
15
+
16
+ Плагин выполняет только HTTP GET. Он не ищет задачи и страницы, не создаёт и
17
+ не изменяет их. OAuth 2.0 flows, браузерные cookies и прохождение
18
+ интерактивного SSO не поддерживаются: credential должен приниматься
19
+ Jira/Confluence REST API без страницы входа.
20
+
21
+ ## 1. Что подготовить
22
+
23
+ До настройки уточните у администратора:
24
+
25
+ 1. Точные внешние имена, например `jira.corp.example` и
26
+ `confluence.corp.example`. В правилах разрешены только точные hostnames, без
27
+ `*.corp.example`.
28
+ 2. Тип инсталляции Jira: Server/Data Center или Cloud.
29
+ 3. Способ API-авторизации и учётную запись только с необходимыми правами
30
+ чтения.
31
+ 4. CIDR подсетей, в которые DNS резолвит корпоративные имена. Не разрешайте
32
+ целиком `10.0.0.0/8`, если достаточно одной подсети.
33
+ 5. Корневой сертификат корпоративного CA, если TLS-сертификат не доверен
34
+ Node.js на машине с DSH Host.
35
+
36
+ Проверять DNS, маршруты, VPN и TLS нужно именно с машины или контейнера, где
37
+ запущен DSH Host, а не только из браузера оператора.
38
+
39
+ ## 2. Установить плагин и выбрать provider
40
+
41
+ Для стандартного web-profile:
42
+
43
+ ```bash
44
+ dsh plugin --profile web add @yadsh/dsh-web-fetch-authenticated
45
+ ```
46
+
47
+ Для локального checkout репозитория:
48
+
49
+ ```bash
50
+ pnpm --filter @yadsh/dsh-web-fetch-authenticated build
51
+ dsh plugin --profile web add ./plugins/dsh-web-fetch-authenticated
52
+ ```
53
+
54
+ Установка регистрирует provider с id `authenticated`, но стандартный профиль
55
+ может продолжать использовать штатный provider `http`. Добавьте в пользовательский
56
+ patch профиля `$DSH_HOME/profiles/web/cordis.patch.yml` следующий override.
57
+ Не перезаписывайте файл целиком, если в нём уже есть другие настройки:
58
+
59
+ ```yaml
60
+ - id: web
61
+ config:
62
+ fetchProvider: authenticated
63
+ ```
64
+
65
+ Если используется другой profile, замените `web` в пути и в команде установки
66
+ на его имя. После изменения перезапустите DSH Host, если профиль не применил
67
+ patch или новый browser bundle автоматически.
68
+
69
+ Откройте **Settings → Plugins → Plugin Configuration → Authenticated Web
70
+ Fetch**. В секции **Provider** должно быть написано:
71
+
72
+ ```text
73
+ ctx.web fetchProvider: pinned to "authenticated"
74
+ ```
75
+
76
+ Если там указан `http`, правила настроены, но `web_fetch` их не использует.
77
+ Переменная `DSH_WEB_FETCH_PROVIDER` помогает только когда значение provider не
78
+ задано самой composition; для стандартного профиля надёжнее явный patch выше.
79
+
80
+ ## 3. Выбрать тип авторизации
81
+
82
+ Используйте тот способ, который включён администраторами именно для REST API:
83
+
84
+ | Контур | Authentication в правиле | Открытые поля | Что хранится как secret |
85
+ | --- | --- | --- | --- |
86
+ | Jira/Confluence Cloud | `Basic auth` | Username = email Atlassian-аккаунта | API token |
87
+ | Server/Data Center с PAT | `Bearer token` | — | PAT |
88
+ | Server/Data Center с локальной учётной записью и разрешённым Basic auth | `Basic auth` | Username | Пароль |
89
+ | Корпоративный API gateway | `API key header` | Header name и, при необходимости, Value prefix | Значение ключа |
90
+
91
+ Новые Atlassian Data Center service accounts используют OAuth 2.0 client
92
+ credentials, который этот плагин пока не реализует. Для текущей версии
93
+ плагина нужен PAT либо отдельно разрешённый администратором Basic/custom-header
94
+ вариант. Сверьтесь с официальными инструкциями Atlassian для
95
+ [Jira Cloud Basic auth](https://developer.atlassian.com/cloud/jira/platform/basic-auth-for-rest-apis/),
96
+ [Confluence Cloud Basic auth](https://developer.atlassian.com/cloud/confluence/basic-auth-for-rest-apis/),
97
+ [Data Center PAT](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html)
98
+ и [Data Center service accounts](https://confluence.atlassian.com/enterprise/service-accounts-overview-1627095923.html).
99
+
100
+ Для заголовка `Authorization` не используйте режим `API key header`: этот
101
+ заголовок намеренно запрещён. Выберите встроенный `Bearer token` или
102
+ `Basic auth`.
103
+
104
+ Credential reference — это не токен, а имя ссылки на него, например
105
+ `CORP_JIRA_PAT`. Имя должно соответствовать шаблону
106
+ `[A-Za-z_][A-Za-z0-9_]*`.
107
+
108
+ В редакторе правила:
109
+
110
+ 1. Введите reference name.
111
+ 2. Вставьте token/password в **Secret value**.
112
+ 3. Нажмите **Save secret** и дождитесь статуса `configured`.
113
+ 4. Сохраните само правило кнопкой **Save rule**.
114
+
115
+ Секрет записывается через credential store DSH и больше не возвращается в UI.
116
+ В YAML храните только reference name. Если credential приходит из read-only
117
+ источника, например окружения Host, UI покажет это и не позволит заменить его;
118
+ задайте переменную окружения с тем же именем вне YAML.
119
+
120
+ Для Jira и Confluence лучше использовать разные reference names и разные
121
+ токены. Один reference допустим, если обе системы действительно используют
122
+ один Cloud API token и одинаковую сервисную учётную запись.
123
+
124
+ ## 4. Создать правило Jira
125
+
126
+ Нажмите **Add rule** и заполните:
127
+
128
+ - **Rule name:** `Corporate Jira`;
129
+ - **Hostnames:** только hostname, без `https://` и пути;
130
+ - **Ports:** оставьте пустым для стандартного 443;
131
+ - **Allowed path patterns:** UI принимает по одному glob на строку;
132
+ - **Authentication:** выбранный на предыдущем шаге способ;
133
+ - **Content adapter:** `Jira issue (REST → clean text)`;
134
+ - **Jira flavor:** `Server / Data Center` либо `Cloud`;
135
+ - **Test URL:** URL реальной задачи, доступной сервисной учётной записи.
136
+
137
+ Минимальный набор путей для Jira Server/Data Center, установленной в корне
138
+ origin:
139
+
140
+ ```text
141
+ /browse/**
142
+ /issues/**
143
+ /rest/api/2/**
144
+ ```
145
+
146
+ Для Jira Cloud замените последнюю строку на:
147
+
148
+ ```text
149
+ /rest/api/3/**
150
+ ```
151
+
152
+ Адаптер распознаёт ссылки вида `/browse/ABC-123` и `/issues/ABC-123`, получает
153
+ задачу через REST v2 (Server/DC) или v3 (Cloud) и возвращает компактный
154
+ Markdown. **Include comments** и **Include issue links** лучше включать только
155
+ при необходимости: они увеличивают ответ и открывают модели больше данных.
156
+
157
+ ### Сетевая политика Jira
158
+
159
+ Для внутреннего hostname откройте **Network policy, redirects, and limits**:
160
+
161
+ - снимите **Public IPs**, если имя не должно резолвиться в публичные адреса;
162
+ - не включайте целиком **Private networks (RFC1918)** без необходимости;
163
+ - внесите согласованные подсети в **Allowed CIDRs**, например
164
+ `10.24.16.0/20`;
165
+ - оставьте **Loopback**, **Link-local**, **Carrier-grade NAT** и
166
+ **IPv6 unique-local** выключенными, если их явно не требует сеть;
167
+ - оставьте **Redirects: Same-origin only** и **Max redirects: 3**.
168
+
169
+ `Allowed CIDRs` разрешает адреса из указанной сети, даже если класс private по
170
+ умолчанию запрещён. `Denied CIDRs` имеет приоритет над разрешением. Плагин
171
+ проверяет все DNS-ответы: если хотя бы один адрес запрещён, запрос блокируется.
172
+
173
+ Пример полностью декларативного правила Jira Data Center:
174
+
175
+ ```yaml
176
+ - id: web-fetch-authenticated
177
+ config:
178
+ enabled: true
179
+ rules:
180
+ - id: corp-jira
181
+ name: Corporate Jira
182
+ description: Read-only access to Jira issues
183
+ enabled: true
184
+ testUrl: https://jira.corp.example/browse/ABC-123
185
+ match:
186
+ schemes: [https]
187
+ hosts: [jira.corp.example]
188
+ allowPaths:
189
+ - /browse/**
190
+ - /issues/**
191
+ - /rest/api/2/**
192
+ auth:
193
+ type: bearer
194
+ credential: CORP_JIRA_PAT
195
+ networkPolicy:
196
+ allowPublic: false
197
+ allowPrivate: false
198
+ allowedCidrs: [10.24.16.0/20]
199
+ redirects:
200
+ mode: same-origin
201
+ maxRedirects: 3
202
+ adapter:
203
+ type: jira
204
+ jiraFlavor: server
205
+ includeComments: false
206
+ includeLinks: false
207
+ ```
208
+
209
+ Значение `CORP_JIRA_PAT` должно быть заранее записано в credential store или
210
+ передано Host через одноимённый credential source. Сам PAT в этот файл не
211
+ помещайте.
212
+
213
+ ## 5. Создать правило Confluence
214
+
215
+ Создайте отдельное правило, даже если права и учётная запись совпадают с Jira:
216
+
217
+ - **Rule name:** `Corporate Confluence`;
218
+ - **Hostnames:** точный hostname Confluence;
219
+ - **Content adapter:** `Confluence page (REST → clean text)`;
220
+ - **Test URL:** URL реальной доступной страницы.
221
+
222
+ Для Confluence Server/Data Center в корне origin используйте:
223
+
224
+ ```text
225
+ /pages/**
226
+ /display/**
227
+ /rest/api/content
228
+ /rest/api/content/**
229
+ ```
230
+
231
+ Для Confluence Cloud достаточно ограничить правило пространством `/wiki`:
232
+
233
+ ```text
234
+ /wiki/**
235
+ ```
236
+
237
+ Адаптер поддерживает страницы по numeric id (`.../pages/123456/...`) и
238
+ Server/DC display URL (`.../display/SPACE/Page+Title`). Он вызывает REST API с
239
+ `body.storage,space,version` и преобразует storage XHTML в Markdown.
240
+
241
+ Пример декларативного правила Confluence Data Center:
242
+
243
+ ```yaml
244
+ - id: web-fetch-authenticated
245
+ config:
246
+ rules:
247
+ - id: corp-confluence
248
+ name: Corporate Confluence
249
+ description: Read-only access to Confluence pages
250
+ enabled: true
251
+ testUrl: https://confluence.corp.example/display/OPS/Runbook
252
+ match:
253
+ schemes: [https]
254
+ hosts: [confluence.corp.example]
255
+ allowPaths:
256
+ - /pages/**
257
+ - /display/**
258
+ - /rest/api/content
259
+ - /rest/api/content/**
260
+ auth:
261
+ type: bearer
262
+ credential: CORP_CONFLUENCE_PAT
263
+ networkPolicy:
264
+ allowPublic: false
265
+ allowPrivate: false
266
+ allowedCidrs: [10.24.32.0/20]
267
+ redirects:
268
+ mode: same-origin
269
+ maxRedirects: 3
270
+ adapter:
271
+ type: confluence
272
+ ```
273
+
274
+ В реальном profile оба правила должны находиться в одном массиве `rules`
275
+ одной записи `id: web-fetch-authenticated`. Два фрагмента выше показаны
276
+ раздельно только для читаемости: если просто вставить оба, более поздний
277
+ override массива заменит предыдущий.
278
+
279
+ ## 6. Пример для Jira и Confluence Cloud на одном tenant
280
+
281
+ У Cloud-продуктов hostname часто общий. Разведите правила непересекающимися
282
+ путями; иначе запрос завершится с `AUTH_FETCH_AMBIGUOUS_MATCH`.
283
+
284
+ ```yaml
285
+ - id: web
286
+ config:
287
+ fetchProvider: authenticated
288
+
289
+ - id: web-fetch-authenticated
290
+ config:
291
+ enabled: true
292
+ rules:
293
+ - id: cloud-jira
294
+ name: Jira Cloud
295
+ enabled: true
296
+ testUrl: https://acme.atlassian.net/browse/ABC-123
297
+ match:
298
+ hosts: [acme.atlassian.net]
299
+ allowPaths:
300
+ - /browse/**
301
+ - /issues/**
302
+ - /rest/api/3/**
303
+ auth:
304
+ type: basic
305
+ username: service-account@acme.example
306
+ passwordCredential: ATLASSIAN_API_TOKEN
307
+ redirects:
308
+ mode: same-origin
309
+ maxRedirects: 3
310
+ adapter:
311
+ type: jira
312
+ jiraFlavor: cloud
313
+
314
+ - id: cloud-confluence
315
+ name: Confluence Cloud
316
+ enabled: true
317
+ testUrl: https://acme.atlassian.net/wiki/spaces/OPS/pages/123456/Runbook
318
+ match:
319
+ hosts: [acme.atlassian.net]
320
+ allowPaths: [/wiki/**]
321
+ auth:
322
+ type: basic
323
+ username: service-account@acme.example
324
+ passwordCredential: ATLASSIAN_API_TOKEN
325
+ redirects:
326
+ mode: same-origin
327
+ maxRedirects: 3
328
+ adapter:
329
+ type: confluence
330
+ ```
331
+
332
+ Проверка пересечения в UI консервативна и может показать warning для двух
333
+ правил с одним hostname, даже когда их `allowPaths` не пересекаются. Это не
334
+ ошибка исполнения: **Diagnose** для Jira URL должен выбрать только
335
+ `cloud-jira`, а для `/wiki/...` — только `cloud-confluence`.
336
+
337
+ ## 7. Проверить настройку
338
+
339
+ Проверяйте каждое правило в таком порядке:
340
+
341
+ 1. В секции **Provider** убедитесь, что provider включён и pinned to
342
+ `authenticated`.
343
+ 2. Убедитесь, что credential показывает `configured`.
344
+ 3. В секции **Diagnostics** вставьте URL задачи/страницы и нажмите
345
+ **Diagnose**. Эта операция проверяет URL, выбор правила, DNS и сетевую
346
+ политику, но не отправляет HTTP-запрос.
347
+ 4. В строке правила нажмите **Test**, вставьте тот же URL и нажмите **Run
348
+ test**. Ожидаемый результат: `ok`, HTTP 200, `Auth applied: yes`, правильный
349
+ `Adapter` и читаемый Markdown в preview.
350
+ 5. В обычной сессии попросите агента прочитать именно полный URL. Например:
351
+
352
+ ```text
353
+ Прочитай https://jira.corp.example/browse/ABC-123 и кратко перечисли
354
+ статус, исполнителя и критерии приёмки.
355
+ ```
356
+
357
+ Для проверки адаптера используйте реальную ссылку на issue/page, а не `/status`
358
+ или главную страницу. Нераспознанный URL намеренно обрабатывается как обычный
359
+ HTML и не доказывает, что REST-адаптер работает.
360
+
361
+ ## 8. Типовые ошибки
362
+
363
+ | Симптом или код | Что проверить |
364
+ | --- | --- |
365
+ | Provider показывает `pinned to "http"` | Добавлен ли override `id: web` с `fetchProvider: authenticated`; применён ли нужный profile |
366
+ | `AUTH_FETCH_NO_MATCHING_RULE` | Точный hostname, HTTPS/HTTP, port и `allowPaths`; path начинается с `/` и чувствителен к структуре URL |
367
+ | `AUTH_FETCH_AMBIGUOUS_MATCH` | Один URL попал сразу под два enabled-правила; разделите host/path/port или отключите лишнее правило |
368
+ | `AUTH_FETCH_CREDENTIAL_MISSING` | Reference name валиден и совпадает с именем сохранённого credential; после ввода секрета нажата **Save secret** |
369
+ | `AUTH_FETCH_NETWORK_DENIED` или `AUTH_FETCH_DNS_POLICY_DENIED` | Все A/AAAA-адреса входят в разрешённые классы/CIDR; VPN и DNS доступны с Host |
370
+ | HTTP 401 | Неверный тип auth, username/token, истёкший PAT или REST API не принимает этот credential |
371
+ | HTTP 403 | Учётная запись аутентифицирована, но не видит проект, issue, space или page |
372
+ | `AUTH_FETCH_REDIRECT_DENIED` | REST-запрос уходит на SSO/login или другой origin; используйте прямой API credential, не расширяйте redirect allowlist без отдельной проверки |
373
+ | `AUTH_FETCH_ADAPTER_FAILED` | REST вернул HTML login page или невалидный JSON; выбран неверный Jira flavor, URL не поддержан либо продукт установлен под нестандартным context path |
374
+ | Ошибка TLS certificate | Добавьте корпоративный CA в trust store процесса Node.js, например через [`NODE_EXTRA_CA_CERTS`](https://nodejs.org/api/cli.html#node_extra_ca_certsfile), и перезапустите Host |
375
+ | Test возвращает HTML с формой входа | URL не распознан адаптером или credential не принимается API; проверьте форму URL и прямой REST-доступ |
376
+
377
+ ## 9. Ограничения URL и корпоративной инфраструктуры
378
+
379
+ - Jira adapter строит REST URL от корня origin: `/rest/api/2/...` или
380
+ `/rest/api/3/...`. Инсталляция по context path вроде
381
+ `https://host.example/jira/...` может распознать issue URL, но её REST path
382
+ автоматически не выводится. Для такого контура используйте root/reverse
383
+ proxy, режим Raw HTTP/HTML или доработанный adapter.
384
+ - Confluence adapter знает root `/rest/api` и Cloud prefix `/wiki/rest/api`.
385
+ Произвольный Server/DC context path автоматически не выводится.
386
+ - Confluence URL вида `/pages/viewpage.action?pageId=123456` не преобразуется
387
+ текущим adapter. Используйте поддерживаемый URL с `/pages/123456/...` или
388
+ `/display/SPACE/Title`; иначе будет Raw HTTP/HTML fallback.
389
+ - Redirect на отдельный SSO-host не превращает браузерную сессию в API-сессию.
390
+ Даже allowlist redirect требует отдельного совпадающего правила и не
391
+ реализует OAuth/cookie flow.
392
+ - HTTP proxy, mTLS client certificate и Kerberos/NTLM не входят в текущие типы
393
+ авторизации. Разместите перед продуктом согласованный HTTPS gateway либо
394
+ расширьте transport отдельной реализацией.
395
+
396
+ ## 10. Короткий security checklist
397
+
398
+ - Используется отдельная read-only сервисная учётная запись.
399
+ - Secret находится в credential store, а не в YAML, prompt или логах.
400
+ - Указаны точные hostnames и минимальные `allowPaths`.
401
+ - Для внутренних адресов заданы узкие `Allowed CIDRs`; лишние классы сети
402
+ выключены.
403
+ - Оставлен `same-origin` redirect, если иной маршрут не подтверждён.
404
+ - Jira comments/links включены только когда действительно нужны.
405
+ - **Diagnose** и **Test** прошли для каждой системы и каждого DNS-сценария.
406
+ - После настройки проверен реальный `web_fetch` из пользовательской сессии.