Skip to content

runtime_context: per-role namespace enforcement behind SGLANG_ROLE_NAMESPACES - #33172

Merged
ch-wan merged 1 commit into
mainfrom
cheng/gc-c3-6-role-enforce
Aug 1, 2026
Merged

ch-wan merged 1 commit into
mainfrom
cheng/gc-c3-6-role-enforce

Conversation

@ch-wan

@ch-wan ch-wan commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Part 3/4 of the config-namespace follow-up stack (RFC: #30696). Base: #33171.

Motivation

publish(role=...) has recorded which process type installed the config since the namespace split; this wires the enforcement that the role was reserved for, so a config read outside a process type's declared surface fails loud instead of silently coupling process types.

Modifications

SGLANG_ROLE_NAMESPACES selects the mode:

  • off (default): no bookkeeping — the mode gate in config_bag is a single dead-branch-prunable check under dynamo (bag reads run inside compiled forwards; pinned by a fullgraph test).
  • record: audit mode — collect (role, namespace) pairs per process, persisting each new pair immediately to SGLANG_ROLE_NAMESPACES_OUT (worker teardown skips atexit), plus a per-process stderr summary at exit.
  • enforce: a bag read outside the role's ROLE_NAMESPACE_SETS entry fails closed with an actionable error; None entries mean full tree.

Sets are filled only where audits back them: dp_controller reads only exec (record-mode plain + DP-attention smokes agree with the module's static read set — the elastic-EP gate). tokenizer observed zero bag reads (per-instance managers read self.server_args by design) but keeps the full tree until the multi-tokenizer disagg shape is audited; encoder / expert_backup / weight_cache_daemon likewise await their deployment shapes.

Verification

Unit tests for all three modes + the fullgraph compile probe; DP-attention smoke under enforce boots and serves with zero violations.

🤖 Generated with Claude Code


CI States

Latest PR Test (Base): 🚫 Run #30707146492
Latest PR Test (Extra): 🚫 Run #30707146389

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a988aa03be

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

global _RECORD_DUMP_REGISTERED
if (role, name) in _RECORDED_NS_READS:
return
_RECORDED_NS_READS.add((role, name))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep record bookkeeping out of compiled forwards

When SGLANG_ROLE_NAMESPACES=record is combined with --enable-torch-compile, namespace access during model tracing reaches this mutation of a module-global set, followed on the first read by optional file I/O and atexit registration. Those Python side effects are incompatible with Dynamo full-graph capture; the piecewise compilation path passes fullgraph=True by default in tc_piecewise_cuda_graph_backend.py:133-146, so audit mode can prevent the model from compiling instead of recording its reads. Move recording outside the traced accessor or otherwise make the record path graph-safe.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — recording is now pruned under tracing via torch.compiler.is_compiling() (lazy sys.modules lookup keeps the module import-light), and a fullgraph regression test compiles a bag read in record mode.

Comment thread python/sglang/srt/runtime_context.py Outdated
Comment on lines +842 to +843
allowed = ROLE_NAMESPACE_SETS.get(role)
if allowed is not None and name not in allowed:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject roles missing from the namespace table

Under enforce, publish(..., role="new_or_misspelled_role") makes dict.get() return None, which is indistinguishable here from an explicitly declared unrestricted role. Consequently, adding or mistyping a process role silently grants access to every namespace, contrary to the advertised fail-closed behavior; use a distinct missing sentinel or validate the role at publication.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — under enforce, a role missing from ROLE_NAMESPACE_SETS is rejected at publish (and defensively at read time) instead of silently inheriting the full tree; covered by a test.

Comment thread python/sglang/srt/runtime_context.py Outdated
"weight_cache_daemon": None,
}

_ROLE_NS_MODE = os.environ.get("SGLANG_ROLE_NAMESPACES", "off")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject unrecognized namespace modes

Any value other than the exact strings off, record, or enforce is accepted here. For example, SGLANG_ROLE_NAMESPACES=Enforce or a value with trailing whitespace enters _check_role_namespace() but matches neither branch, silently disabling enforcement instead of reporting the misconfiguration. Validate or normalize the environment value when it is loaded.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the env value is normalized (strip + lower) and anything outside off/record/enforce raises at import; covered by a test.

@ch-wan
ch-wan force-pushed the cheng/gc-c3-4-tests branch from ee1dfd2 to 352ff4e Compare August 1, 2026 07:33
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from d37d8a4 to 3879e20 Compare August 1, 2026 07:33

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3879e2018e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread python/sglang/srt/runtime_context.py Outdated
# typo into "off").
from sglang.srt.environ import envs

return _validated_role_ns_mode(envs.SGLANG_ROLE_NAMESPACES.get() or "off")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject an explicitly empty namespace mode

When an operator explicitly sets SGLANG_ROLE_NAMESPACES= (for example, through an unset deployment-template value), the or "off" fallback converts that invalid value into off and silently disables enforcement. Fresh evidence beyond the earlier validation thread is that the new _validated_role_ns_mode() check is still bypassed specifically for the empty string; the field already defaults to off when the variable is absent, so the fallback should not replace an explicitly supplied value.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — the or \"off\" fallback is gone: an explicitly empty SGLANG_ROLE_NAMESPACES= now reaches the validator and raises instead of silently disabling enforcement (absence still defaults to off via the EnvStr default).

@ch-wan

ch-wan commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Review disposition

All review threads resolved (env registration, OUT-file stderr on failure, tokenizer comment). No remaining open findings from this review pass.

@ch-wan
ch-wan force-pushed the cheng/gc-c3-4-tests branch 2 times, most recently from edd6acc to efbcf96 Compare August 1, 2026 08:10
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from 3879e20 to 0b5a5eb Compare August 1, 2026 08:10
@ch-wan

ch-wan commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

Review disposition (r3)

Clean — no open findings.

Prior threads remain resolved. Also verified latest head fixes:

  • record-mode publish {role} - OUT marker for signal-killed zero-read workers
  • empty SGLANG_ROLE_NAMESPACES= fails validation (no silent off)

No PENDING review this round (zero issues).

@ch-wan
ch-wan force-pushed the cheng/gc-c3-4-tests branch from efbcf96 to 3b6ec54 Compare August 1, 2026 15:22
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from 0b5a5eb to eac3495 Compare August 1, 2026 15:22
@ch-wan
ch-wan force-pushed the cheng/gc-c3-4-tests branch from 3b6ec54 to 6f94dae Compare August 1, 2026 15:30
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from eac3495 to 6a68c5e Compare August 1, 2026 15:30
@ch-wan
ch-wan force-pushed the cheng/gc-c3-4-tests branch from 6f94dae to dbb9edc Compare August 1, 2026 15:47
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from 6a68c5e to 9f6e1cb Compare August 1, 2026 15:47
@ch-wan
ch-wan force-pushed the cheng/gc-c3-4-tests branch from dbb9edc to 5dcfb35 Compare August 1, 2026 15:54
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from 9f6e1cb to 437fefa Compare August 1, 2026 15:54
@ch-wan
ch-wan force-pushed the cheng/gc-c3-4-tests branch from 5dcfb35 to 1b9e720 Compare August 1, 2026 15:58
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from 437fefa to 27f4422 Compare August 1, 2026 15:58
@ch-wan
ch-wan force-pushed the cheng/gc-c3-4-tests branch from 1b9e720 to 78318da Compare August 1, 2026 15:58
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from 27f4422 to d9aa7f8 Compare August 1, 2026 15:58
Base automatically changed from cheng/gc-c3-4-tests to main August 1, 2026 15:59
…MESPACES

publish(role=...) has recorded provenance since the namespace split; this
wires the enforcement the role was reserved for. SGLANG_ROLE_NAMESPACES
selects the mode:

- off (default): no bookkeeping; the mode gate in config_bag stays a
  dead-branch-prunable check under dynamo (bag reads run inside compiled
  forwards — pinned by a fullgraph test).
- record: audit mode — collect (role, namespace) pairs per process and
  persist each new pair immediately to SGLANG_ROLE_NAMESPACES_OUT (worker
  teardown skips atexit), plus a per-process stderr summary at exit.
- enforce: a bag read outside the role's ROLE_NAMESPACE_SETS entry fails
  closed with an actionable error; None entries mean full tree.

Sets are filled only where audits back them: dp_controller reads only
exec (record-mode plain + DP-attention smokes agree with the module's
static read set — the elastic-EP gate). tokenizer observed zero bag
reads (per-instance managers read self.server_args by design) but keeps
the full tree until the multi-tokenizer disagg shape (TokenizerWorker's
get_disagg read) is audited; encoder / expert_backup /
weight_cache_daemon likewise await their deployment shapes.

Verified end-to-end: DP-attention smoke under enforce boots and serves
with zero violations.
@ch-wan
ch-wan force-pushed the cheng/gc-c3-6-role-enforce branch from d9aa7f8 to 96a560f Compare August 1, 2026 15:59
@ch-wan
ch-wan merged commit 7071cfb into main Aug 1, 2026
3 checks passed
@ch-wan
ch-wan deleted the cheng/gc-c3-6-role-enforce branch August 1, 2026 15:59
saturn-acc pushed a commit to saturn-acc/sglang that referenced this pull request Aug 16, 2026
…MESPACES (sgl-project#33172)

publish(role=...) has recorded provenance since the namespace split; this
wires the enforcement the role was reserved for. SGLANG_ROLE_NAMESPACES
selects the mode:

- off (default): no bookkeeping; the mode gate in config_bag stays a
  dead-branch-prunable check under dynamo (bag reads run inside compiled
  forwards — pinned by a fullgraph test).
- record: audit mode — collect (role, namespace) pairs per process and
  persist each new pair immediately to SGLANG_ROLE_NAMESPACES_OUT (worker
  teardown skips atexit), plus a per-process stderr summary at exit.
- enforce: a bag read outside the role's ROLE_NAMESPACE_SETS entry fails
  closed with an actionable error; None entries mean full tree.

Sets are filled only where audits back them: dp_controller reads only
exec (record-mode plain + DP-attention smokes agree with the module's
static read set — the elastic-EP gate). tokenizer observed zero bag
reads (per-instance managers read self.server_args by design) but keeps
the full tree until the multi-tokenizer disagg shape (TokenizerWorker's
get_disagg read) is audited; encoder / expert_backup /
weight_cache_daemon likewise await their deployment shapes.

Verified end-to-end: DP-attention smoke under enforce boots and serves
with zero violations.
jakki-amd pushed a commit to jakki-amd/sglang that referenced this pull request Sep 9, 2026
…MESPACES (sgl-project#33172)

publish(role=...) has recorded provenance since the namespace split; this
wires the enforcement the role was reserved for. SGLANG_ROLE_NAMESPACES
selects the mode:

- off (default): no bookkeeping; the mode gate in config_bag stays a
  dead-branch-prunable check under dynamo (bag reads run inside compiled
  forwards — pinned by a fullgraph test).
- record: audit mode — collect (role, namespace) pairs per process and
  persist each new pair immediately to SGLANG_ROLE_NAMESPACES_OUT (worker
  teardown skips atexit), plus a per-process stderr summary at exit.
- enforce: a bag read outside the role's ROLE_NAMESPACE_SETS entry fails
  closed with an actionable error; None entries mean full tree.

Sets are filled only where audits back them: dp_controller reads only
exec (record-mode plain + DP-attention smokes agree with the module's
static read set — the elastic-EP gate). tokenizer observed zero bag
reads (per-instance managers read self.server_args by design) but keeps
the full tree until the multi-tokenizer disagg shape (TokenizerWorker's
get_disagg read) is audited; encoder / expert_backup /
weight_cache_daemon likewise await their deployment shapes.

Verified end-to-end: DP-attention smoke under enforce boots and serves
with zero violations.
Atituiset pushed a commit to Atituiset/sglang that referenced this pull request Sep 10, 2026
…MESPACES (sgl-project#33172)

publish(role=...) has recorded provenance since the namespace split; this
wires the enforcement the role was reserved for. SGLANG_ROLE_NAMESPACES
selects the mode:

- off (default): no bookkeeping; the mode gate in config_bag stays a
  dead-branch-prunable check under dynamo (bag reads run inside compiled
  forwards — pinned by a fullgraph test).
- record: audit mode — collect (role, namespace) pairs per process and
  persist each new pair immediately to SGLANG_ROLE_NAMESPACES_OUT (worker
  teardown skips atexit), plus a per-process stderr summary at exit.
- enforce: a bag read outside the role's ROLE_NAMESPACE_SETS entry fails
  closed with an actionable error; None entries mean full tree.

Sets are filled only where audits back them: dp_controller reads only
exec (record-mode plain + DP-attention smokes agree with the module's
static read set — the elastic-EP gate). tokenizer observed zero bag
reads (per-instance managers read self.server_args by design) but keeps
the full tree until the multi-tokenizer disagg shape (TokenizerWorker's
get_disagg read) is audited; encoder / expert_backup /
weight_cache_daemon likewise await their deployment shapes.

Verified end-to-end: DP-attention smoke under enforce boots and serves
with zero violations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant