feat(auth): extract admission identity keys and composition - #218
Conversation
Add canonical session/sender keys and overlay composition without changing default runtime admission. Empty UID overlays still follow the current UMO session switches. Unique-session rewrites do not change the session key. Fixes #214 AI-Generated: true Generated-At: 2026-09-17T15:36:11Z
Count a session or sender as listed only when an admission field is a real bool. Garbage keys must not satisfy unlisted-deny. Reuse the typed service-config helper in LLM and block setters. Related: #214 AI-Generated: true Generated-At: 2026-09-17T15:57:36Z
Review follow-upReviewed against #214 / #212. Default empty-UID admission, unique-session group keys, and the whitelist matcher look correct. Pushed Fixed
Intentionally unchanged
This comment is not an approval. |
|
💡 To run commands without mentioning me, run one command with a mention first — |
Non-dict session_service_config rows still crashed the TTS getter/setter after LLM and block paths started using _service_config. Invalid tts_enabled values now default to enabled, matching the bool-only admission overlay parser. Related: #214 AI-Generated: true Generated-At: 2026-09-17T16:25:18Z
BegoniaHe
left a comment
There was a problem hiding this comment.
AI-assisted review
Reviewed against #214 / #212 and the current branch including 082be4919.
Matches A1
- Group session keys ignore unique-session
session_idrewrites (session:{platform}:group:{group_id}). - Private session keys compare with
Subject.imon the peer id. compose_admission()covers the parent composition table: refusal wins, sender LLM is more specific,session_blockedoverrides a personal LLM exception, garbage overlay values are unlisted.- Empty
scope=senderrows still follow current UMO session switches. Lookups stay onevent.unified_msg_origin. - Pipeline order and
WhitelistCheckStage/id_whitelistare unchanged.
Fixed in this review
- TTS getter/setter in
SessionServiceManagerstill used rawor {}after_service_configwas extracted for LLM/block. A non-dictsession_service_configrow crashed TTS and could return a non-bool. They now use the helper, treat invalidtts_enabledas unwritten/enabled, and keep other overlay keys when writing TTS.
Intentionally unchanged
session_enabled=Falsedoes not dropadmit_event; it is exposed onAdmissionDecisionfor SessionStatusCheck / later slices.should_process_llm_requeststill ignoresblockedflags. Senderblockedis readable, not wired into the pipeline (A3).- CodeQL
py/ineffectual-statementon Protocol...andpy/uninitialized-local-variableonadmit_eventare false positives (repo-wide Protocol stub style;admit_eventis assigned immediately before use).
Residual risk
- Group messages with an empty
group_idmintsession:{platform}:group:unknown. That matches A1's "always use group_id" rule; A2 should not treatunknownas a real room. - A pre-existing
scope=senderrow already affects LLM overlay composition. A1 wants that; A3 still owns persistence.
This is not an approval or merge. Human maintainer review is still required.
Replace Protocol ellipsis stubs with NotImplementedError and stop naming a compose_admission local after AdmissionDecision.admit_event. Related: #214 AI-Generated: true Generated-At: 2026-09-17T16:38:15Z
BegoniaHe
left a comment
There was a problem hiding this comment.
AI-assisted review
Reviewed against #214 / #212 and the current branch including 8a35a2ecf.
Matches A1
- Group session keys ignore unique-session
session_idrewrites (session:{platform}:group:{group_id}). - Private session keys compare with
Subject.imon the peer id. compose_admission()covers the parent composition table: refusal wins, sender LLM is more specific,session_blockedoverrides a personal LLM exception, garbage overlay values are unlisted.- Empty
scope=senderrows still follow current UMO session switches. Lookups stay onevent.unified_msg_origin. - Pipeline order and
WhitelistCheckStage/id_whitelistare unchanged.
Fixed in this review
- CodeQL
py/ineffectual-statementonAdmissionEventProtocol...stubs. Methods nowraise NotImplementedError, matching the existingfix(kb): resolve codeql protocol findingspattern. - CodeQL
py/uninitialized-local-variableoncompose_admission. The local namedadmit_eventcollided withAdmissionDecision.admit_event; composition now usesrefusedand writes the dataclass fields directly.
Intentionally unchanged
session_enabled=Falsedoes not dropadmit_event; it is exposed onAdmissionDecisionfor SessionStatusCheck / later slices.should_process_llm_requeststill ignoresblockedflags. Senderblockedis readable, not wired into the pipeline (A3).
Residual risk
- Group messages with an empty
group_idmintsession:{platform}:group:unknown. That matches A1's "always use group_id" rule; A2 should not treatunknownas a real room. - A pre-existing
scope=senderrow already affects LLM overlay composition. A1 wants that; A3 still owns persistence.
Checks run: ruff format/check and pyright on admission.py; 220 pytest cases across admission, session manager, waking/whitelist/session-status, authorization, and import boundaries. Full make check / blocking pytest were not run.
This is not an approval or merge. Human maintainer review is still required.
Keep the hard-cap invariant (flush before the long debounce) without a tight processed_at-started_at assertion that flakes on overloaded CI. Related: #214 AI-Generated: true Generated-At: 2026-09-17T17:00:42Z
DingTalk unique-session rewrites group session_id to the sender id. The canonical session key must still use group_id. Related: #214 AI-Generated: true Generated-At: 2026-09-17T17:00:42Z
AI-assisted reviewReviewed against #214 / #212 on Matches A1
CI / CodeQL
Intentionally unchanged
Residual risk
Checks run: This is not an approval or merge. Human maintainer review is still required. |
Summary
Extract canonical session/sender admission keys and the overlay composition function so later slices can replace the whitelist and add UID rules. Default runtime admission is unchanged: empty sender overlays still follow the current UMO session switches.
Related issue
Fixes #214
Related: #212
Behavior
session:{platform_instance}:group:{group_id}whether unique-session is on or off. They never use the rewrittensender_groupsession id.session:{platform_instance}:private:{peer_id}and can be compared withSubject.im(im:{platform_instance}:{bot}:{sender_id}).compose_admission()implements the parent composition table (unlisted_*, UMOsession_enabled/session_blocked/llm_enabled, UIDblocked/llm_enabled). Refusal wins;session_blockedoverrides a personal LLM exception.SessionServiceManagerstill readssession_service_configfromscope=umo.scope=senderis readable and empty by default. New query:is_sender_blocked.WhitelistCheckStageandid_whiteliststay.Non-goals
Deleting the whitelist, Dashboard/OpenAPI changes,
/usercommands, binding persona/KB to senders, changingllm_access, or migrating unique-session/llm disableonto the canonical session key (A2).Implementation notes
Identity and composition live in
astrbot/core/auth/admission.pyas pure functions so they do not importAstrMessageEvent(avoids an auth ↔ event cycle). A1 lookups still useevent.unified_msg_originso unique-session/llm disablekeeps today's meaning. No docs or OpenAPI change: there is no user-visible behavior shift.Validation
Ruff format/check passed. Pyright reported 0 errors. The listed pytest files passed (286 tests).
make checkand the full blocking pytest suite were not run.Compatibility and risk
No public API, Dashboard protocol, OpenAPI, or docs change. Isolated
should_process_llm_requestnow also reads emptyscope=senderoverlays; with no UID rows this matches the previous UMO-only LLM switch.session_blockedstill does not gate that method (SessionStatusCheck remains the event drop). A written senderllm_enabledwould already take effect if one existed.Checklist
docs/zh/anddocs/en/.docs/public/openapi.json, and tests change together when routes or schemas change.pyproject.toml,requirements.txt, anduv.locktogether.!and aBREAKING CHANGE:footer.Agent note
Goal: land A1 of #212 — stable session/sender keys plus composition, without changing default admission. Touched
astrbot/core/auth/admission.py,astrbot/core/star/session_llm_manager.py, and focused unit tests for composition, unique-session keys, empty-UID equivalence, and the unchanged whitelist matcher. Checks actually run are listed above; fullmake check/ blocking pytest were not. Residual risk: a pre-existingscope=senderrow would now affect LLM overlay composition, which A1 wants, but A3 is still the persistence owner. Tools: OpenCode. This write-up is not the required separate AI-assisted review.