Skip to content

docs(permissions): state the allowed_ip_ranges save refusal, the live clear and the env recovery - #30382

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-30314-allowed-ip-docs
Nov 5, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-30314-allowed-ip-docs

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by 田騏 · project thread

Fixes #30314

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:认证文档的 allowed_ip_ranges 一行加了一句话并链到一个短小节,写明三件事:保存一份不匹配自己当前地址的列表会被拒(400 SETTINGS_VALIDATION,提示里写明你的地址和救援办法);清空字段立即生效、回到部署自己声明的列表;已被锁在外面时把 OS_AUTH_ALLOWED_IP_RANGES 设为空值并重启。
  • 为什么改:PR fix(plugin-auth)!: clearing the allowed IP ranges applies at once, and a console save that leaves out the saving address is refused #30309 已经上线了这套行为,但文档一个字没提;管理员读文档时不知道保存会被拒、也不知道被锁后怎么进来。
  • 风险与回滚:只改一页文档,不动代码;回滚即撤本 PR。
  • 先看:content/docs/permissions/authentication.mdx 的 Network 表格那一行,以及紧跟在“How enforcement works”引用块后面的新小节 “Saving, clearing and lockout recovery”。
  • 两分钟验证:pnpm check:doc-anchors,预期 exit 0(行内链接指向的新小节锚点存在)。
  • 需要你做的:无,席位落地。

What changes

content/docs/permissions/authentication.mdx only. The allowed_ip_ranges row gains one sentence that links a new short subsection, Saving, clearing and lockout recovery, under Network. Each statement was read from the code merged by PR #30309 (at fdad1786e8), not from its description:

  • The save refusal. The settings save route PUT /api/settings/:namespace (packages/services/service-settings/src/settings-routes.ts:320, called by the console at ui/apps/console/src/pages/settings/api.ts:172) hands the request's peer address and headers to setMany (settings-routes.ts:354-368). The write predicate registered for auth.allowed_ip_ranges (packages/plugins/plugin-auth/src/auth-plugin.ts:2551-2556) resolves the caller's address with the auth manager's own resolveClientAddress and matches it with the gate's own ipMatchesRange (packages/plugins/plugin-auth/src/allowed-ip-ranges.ts:148-152). A refusal becomes SettingsValidationError (packages/services/service-settings/src/settings-service.ts:2722), answered 400 SETTINGS_VALIDATION with details.fields (settings-routes.ts:397), field code invalid_value and constraint.clientAddress. The message is the copy at allowed-ip-ranges.ts:85-123, in the caller's language, ending with the recovery sentence (allowed-ip-ranges.ts:93).
  • Clearing. A cleared value resolves with source default; applySettings then puts back the deployment's declared list, or none (auth-plugin.ts:2328-2334). That list is captured after the auth:configure hook (auth-plugin.ts:750, :792). The pass re-runs on every auth settings change (auth-plugin.ts:2569), so no restart. A clear is never refused (allowed-ip-ranges.ts:145).
  • Recovery. effectiveEnvOverride treats any string as an override, the empty string included (settings-service.ts:1378-1379); the key has no default, so coerceEnvValue keeps '' (settings-service.ts:3843-3857, packages/services/service-settings/src/manifests/auth.manifest.ts:366-372). The value is then source: 'env', so isExplicit holds and parseAllowedIpRanges('') gives no list (auth-plugin.ts:2094, :2328-2329). An override in force also locks the key against writes (settings-service.ts:2406-2408, answered 409 SETTINGS_LOCKED at settings-routes.ts:378-379).

Where the code says more than, or something other than, the card's Wanted lines:

  1. Wanted 1 says "leaves out" the caller's address; the code refuses a list in which no entry matches it. ipMatchesRange matches IPv4 CIDR and exact addresses only, so the page says "no entry matches". It also states two cases the Wanted line does not: when the server cannot establish the caller's address, any non-empty list is refused (allowed-ip-ranges.ts:152-156); and only a change is judged, so saving the list already in force again is not refused (settings-service.ts:2695). Writes inside the server carry no request and are not judged (allowed-ip-ranges.ts:143).
  2. The door is the settings API, not the console alone. The check sits on PUT /api/settings/auth. The console calls it, and so can any HTTP client, which gets the same refusal.
  3. Wanted 3's recovery is not a permanent fix by itself. While OS_AUTH_ALLOWED_IP_RANGES is set, the stored list is kept but not used, and a save to the field is refused with 409 SETTINGS_LOCKED. When the variable is removed, the stored list applies again at the next restart. The page states this as it is.

Tests

None: a docs-only change. No code, test or i18n file is touched. No changeset: content/docs/ ships in no published package, so this PR carries skip-changeset.

Acceptance notes

  • Placement. The order asked for the subsection right after the table. The table is followed by the hardening section's own "How enforcement works" blockquote, which is about password expiry and MFA. A heading placed before it would have put that blockquote under the new heading. So the subsection sits right after the blockquote, still under Network, and the row links to it.
  • No console path to clear a stored list while the env override is set. Follows from point 3 above: an admin who recovers with the empty variable cannot then clear the stored list in the console, because the key is locked. Removing the variable brings the list back. Named for the seat; not filed.
  • "Changes take effect immediately" in the section intro. The hardening intro says every toggle applies without a restart. PR fix(plugin-auth)!: clearing the allowed IP ranges applies at once, and a console save that leaves out the saving address is refused #30309's acceptance notes measured that clearing lockout_threshold or max_concurrent_sessions_per_user keeps the last stored value until a restart. That family is the seat's (named there); this PR does not touch the intro.
  • check:liveness is red on this tree, from main. pnpm --filter @objectstack/spec run check:liveness exits 1: the ledger entry query/searchFields cites packages/objectql/src/engine.ts, which no longer names the key after f672e0d moved its docblocks out. This diff does not touch that file or the ledger.

Verification

Derived gates: 45 derived, 45 run, 44 exit 0, 1 exit 1 (from main)
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 45 commands for the one changed path, at head e4fc7bccf3.
  • Each ran with its exit code captured before any pipe. 44 exit 0.
  • First pass, 5 refused with PREREQUISITE NOT MET (exit 3: check:doc-formula-expressions, check:doc-security-posture, check:skill-examples, check:docs-transcript-drift) or a missing packages/spec/json-schema (check:docs, exit 1). After building @objectstack/spec, @objectstack/formula, @objectstack/lint, and the @objectstack/client / @objectstack/client-react closures under the verify lock (VERDICT command-exit 0 both times), all five re-ran to exit 0.
  • pnpm --filter @objectstack/spec run check:liveness: exit 1, the main finding above.
  • --ran reconciliation: "45 derived famil(ies) accounted for — 45 run, 0 NOT-MEASURED".
  • git merge origin/main: already up to date (origin/main = fdad1786e8).
  • NOT MEASURED here, CI's own: the Build Docs and Plan Test Core shards jobs the paths schedule.

🤖 Generated with Claude Code

… clear and the env recovery

The authentication page's allowed_ip_ranges row now links a short
subsection that says what the merged code does: a settings save whose
list matches none of the saving request's own address (resolved under
server.trustProxy) is refused with 400 SETTINGS_VALIDATION, a clear
applies at once and returns to the deployment's declared list, and an
empty OS_AUTH_ALLOWED_IP_RANGES is an env override in force that opens
the gate at the next restart while it locks the field.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2ebbZkr2QAEG1x7UC8
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 5, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Nov 5, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8

席位核对 — ACCEPT · domain:devx#2 · Head-sha 38ea0610de71bbb0c5ddbe02feb5693b9a5d5cbe · 2026-11-05T09:47Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant