+
    jHàj4<  ã                  ó’  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RIt^ RIH	t	H
t
 ^ RIHt ^ RIHtHtHt ]'       d   ^ RIHt ]P&                  ! ]4      tRtR	R
]3t ! R R]4      t]	! RR7       ! R R4      4       tR R ltR R ltR R ltR R ltR R ltRRRRRR/R R llt R  R! lt!RRRRRR/R" R# llt"R$t#R% t$R& t%R# )'u   One frozen routing identity per inbound gateway event.

A multiplexed gateway answers three questions about every event, and until now answered them in
three places that only agreed because they read the same fallback chain: WHICH bot received it
(``_transport_owner``), WHO may admit it (``_authorization_home_for_source``) and WHERE the turn
runs (``_resolve_profile_home_for_source`` / ``_session_key_profile``). :func:`resolve_identity`
answers all three once and pins the result on the source as a wire-invisible dynamic attribute
(like ``_transport_adapter_ref``); the existing helpers read it when present and keep their
fallback chain when absent, so a source built outside the runner still resolves as before.

``SessionSource.profile`` stays the serialized runtime profile â€” ``None`` on the wire means the
receiving bot's own profile â€” so nothing here changes the wire format or any historical
``agent:main`` key.
)ÚannotationsN)Úsuppress)Ú	dataclassÚfield)ÚPath)ÚTYPE_CHECKINGÚAnyÚOptional)ÚSessionSourceÚ	_identityÚ_transport_adapter_refÚ_authorization_profile_homec                  ó   € ] tR t^$tRtRtR# )ÚIdentityUnresolvedzèUnder multiplexing the event's runtime profile could not be established (an explicit
``profile_routes`` entry targets a profile this gateway does not serve). Callers drop the
event; it must never fall through to the default profile.© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   ó    Ú=/home/ubuntu/.hermes/hermes-agent/gateway/session_identity.pyr   r   $   s   † õAr   r   T)Úfrozenc                  óà   € ] tR t^*t$ RtR]R&   R]R&   R]R&   R]R&   RtR	]R
&   ]! RRRR7      tR]R&   ]! RRRR7      t	R	]R&   ]
R R l4       t]
R R l4       t]
R R l4       tR R ltRtR# )ÚRoutingIdentityu  Everything a turn needs to know about who it is, resolved once at ingress.

``transport_profile`` owns the receiving adapter (its credential and allowlist);
``runtime_profile`` is the profile that executes the turn â€” the same name unless a
``profile_routes`` entry re-homed the event. Both are explicit (``"default"`` is spelled out);
``None`` never means default here. ``multiplexed`` is False for a standalone gateway, whose
keys stay in the legacy ``agent:main`` namespace whatever profile it was launched with.
ÚstrÚtransport_profileÚruntime_profiler   Úauthorization_homeÚruntime_homeTÚboolÚmultiplexedNF)ÚdefaultÚcompareÚhashzOptional[weakref.ref]Ú	transportÚtransport_inferredc               ó   € V ^8„  d   QhRR/# )é   Úreturnr   r   )Úformats   "r   Ú__annotate__ÚRoutingIdentity.__annotate__D   s   € ÷ @ñ @˜3ñ @r   c                ó2   € ^ RI Hp V! V P                  4      # )u•   ``agent:<ns>`` prefix for this identity's session keys â€” byte-identical to
:func:`gateway.session._session_key_namespace` for every historical key.)Ú_session_key_namespace)Úgateway.sessionr/   Úsession_key_profile)Úselfr/   s   & r   Ú	namespaceÚRoutingIdentity.namespaceC   s   € õ 	;Ù% d×&>Ñ&>Ó?Ð?r   c               ó   € V ^8„  d   QhRR/# )r)   r*   r   r   )r+   s   "r   r,   r-   K   s   € ÷ .ñ .˜Dñ .r   c                	ó(   € V P                   R ,          # )zstate.db)r    ©r2   s   &r   Ú
store_pathÚRoutingIdentity.store_pathJ   s   € à× Ñ  :Õ-Ð-r   c               ó   € V ^8„  d   QhRR/# )r)   r*   úOptional[str]r   )r+   s   "r   r,   r-   O   s   € ÷ Bñ B ]ñ Br   c                óB   € V P                   '       d   V P                  # R# )z¨The ``profile=`` argument :func:`gateway.session.build_session_key` expects for this
identity: the runtime profile under multiplexing, else ``None`` (legacy namespace).N)r"   r   r7   s   &r   r1   Ú#RoutingIdentity.session_key_profileN   s    € ð (,×'7×'7Ð'7ˆt×#Ñ#ÐA¸TÐAr   c               ó   € V ^8„  d   QhRR/# )r)   r*   r   r   )r+   s   "r   r,   r-   T   s   € ÷ Hñ H˜ñ Hr   c                óB   € V P                   e   V P                  4       # R# )zGThe live receiving adapter, or None when it is gone or was never known.N)r&   r7   s   &r   ÚadapterÚRoutingIdentity.adapterT   s   € à#'§>¡>Ò#=ˆt�~‰~ÓÐGÀ4ÐGr   r   )r   r   r   r   r   Ú__annotations__r"   r   r&   r'   Úpropertyr3   r8   r1   r@   r   r   r   r   r   r   *   s¡   ‡ ñð ÓØÓØÓØÓØ€K�Óñ (-°TÀ5ÈuÔ'U€IÐ$ÓUñ
  %¨U¸EÈÔNÐ˜ÓNàô@ó ð@ð ô.ó ð.ð ôBó ðB÷
Hñ Hr   r   c               ó    € V ^8„  d   QhRRRR/# )r)   Úsourcer   r*   úOptional[RoutingIdentity]r   )r+   s   "r   r,   r,   Y   s   € ÷ Gñ G˜ð GÐ 9ñ Gr   c                óX   € \        V \        R4      p\        V\        4      '       d   V# R# )zDThe identity pinned on *source* by :func:`resolve_identity`, if any.N)ÚgetattrÚ_IDENTITY_ATTRÚ
isinstancer   ©rE   Úidentitys   & r   Úidentity_ofrM   Y   s'   € ä�vœ~¨tÓ4€HÜ! (¬O×<Ò<ˆ8ÐFÀ$ÐFr   c               ó    € V ^8„  d   QhRRRR/# )r)   rE   r   r*   ÚNoner   )r+   s   "r   r,   r,   _   s   € ÷ 
ñ 
˜3ð 
 4ñ 
r   c                ó  € \         RRR3 F.  p\        \        4      ;_uu_ 4        \        W4       RRR4       K0  	  \        \        4      ;_uu_ 4        RV n        RRR4       R#   + '       g   i     Kl  ; i  + '       g   i     R# ; i)u½  Drop the pinned identity AND the routed runtime profile so the next :func:`canonical_identity`
re-routes from scratch â€” for sources a caller reuses across events whose routing may differ (a
guild's cached voice source is shared by every speaker, and ``profile_routes[].user_id`` routes
per speaker). ``source.profile`` is the previous event's routing *result*; left in place it
short-circuits the route and the new speaker runs as the old one.Úprofile_route_rejectedr   Ú_rejected_route_profileN)rI   r   ÚAttributeErrorÚdelattrÚprofile)rE   Úattrs   & r   Úclear_identityrW   _   sh   € ô  Ð!9Ð;XÐZsÓtˆÜ”n×%Õ%Ü�FÔ!÷ &Ñ%ñ uô 
”.×	!Õ	!ØˆŒ÷ 
"Ñ	!÷ &×%Ð%úç	!×	!Ð	!ús   ¥A&ÁA:Á&A7Á:B	c               ó    € V ^8„  d   QhRRRR/# )r)   rE   r   r*   r;   r   )r+   s   "r   r,   r,   l   s   € ÷ añ a ð a¨ñ ar   c                ó`   € \        V 4      pVe   VP                  '       d   VP                  # R# )zÍThe receiving bot's profile to persist alongside a routing entry (``SessionEntry.transport_profile``);
None outside multiplexing or when nothing resolved the source (an unknown transport is never guessed).N)rM   r"   r   rK   s   & r   Útransport_profile_ofrZ   l   s0   € ô ˜6Ó"€HØ)1Ò)=À(×BV×BVÐBVˆ8×%Ñ%Ð`Ð\`Ð`r   c               ó$   € V ^8„  d   QhRRRRRR/# )r)   rE   r
   Úchangesr   r*   r   )r+   s   "r   r,   r,   s   s!   € ÷ 	ñ 	˜=ð 	°Sð 	¸]ñ 	r   c                óŠ   € \         P                  ! V 3/ VB p\         F!  p\        WR4      pVf   K  \	        W#V4       K#  	  V# )zÐ:func:`dataclasses.replace` that keeps the wire-invisible provenance (transport ref,
authorization home, identity). A plain ``replace`` silently produces a source the runner
can only route through heuristics.N)ÚdataclassesÚreplaceÚ_PROVENANCE_ATTRSrH   Úsetattr)rE   r\   ÚcopiedÚnameÚvalues   &,   r   Úreplace_sourcere   s   sF   € ô × Ò  Ñ3¨7Ñ3€Fß!ˆÜ˜ dÓ+ˆØÔÜ�F %Ö(ñ "ð €Mr   c               ó    € V ^8„  d   QhRRRR/# )r)   rd   r   r*   r;   r   )r+   s   "r   r,   r,      s   € ÷ ñ �ð ˜ñ r   c                ój   € \        V \        4      '       d   V P                  4       MR pT;'       g    R# )Ú N)rJ   r   Ústrip)rd   Útexts   & r   Ú_namerk      s'   € Ü& u¬c×2Ò2ˆ5�;‰;Œ=¸€DØ�<ˆ<�4Ðr   r@   r   Úprimary_homec               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r)   rE   r
   Úrunnerr   r@   r   r;   rl   úOptional[Path]r*   rF   r   )r+   s   "r   r,   r,   „   s>   € ÷ ñ ØðØ&)ðØ47ðà$ðà;Iðð ñr   c               ó    € \        V 4      pVe   V#  \        WW#VR7      #   \         d"   p\        P	                  RT4        Rp?R# Rp?ii ; i)uB  The identity already pinned on *source*, else :func:`resolve_identity` â€” the one call every
ingress path makes FIRST, before any key is derived. ``None`` = unresolved under multiplexing
(``source.profile_route_rejected`` is set): the caller drops the event and says so once; it
must never fall through to ``agent:main``.N)rn   r@   r   rl   zidentity unresolved: %s)rM   Úresolve_identityr   ÚloggerÚdebug)rE   rn   r@   r   rl   rL   Úexcs   &$$$$  r   Úcanonical_identityru   „   sW   € ô ˜6Ó"€HØÒØˆðÜØ¨7Ø%ô'ð 	'øô ô Ü�‰Ð.°Ô4Ýûðús   “! ¡A¬AÁAc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r)   rE   r
   rn   r   r   r;   r*   rF   r   )r+   s   "r   r,   r,   ˜   s,   € ÷ %ñ %Øð%Ø&)ð%Ø>Kð%àñ%r   c          	     ó   € \        V4      pVf   R# \        \        \        VRR4      RR4      4      '       g   R# \        V 4      pVe   V# ^ RIHp ^ RIHp \        \        VRR4      4      ;'       g    Rp\        \        V R	R4      4      ;'       g    TpW78X  d   \        V! 4       4      MV! V4      p	Wƒ8X  d   T	M\        VP                  V 4      4      p
W�n
        \        W8WšR
RR7      p\        V \        V4       V# )un  Pin the identity of a source rebuilt from durable state (``SessionEntry.origin``, a
``sessions`` row, a cached copy) â€” no live adapter, so ``transport=None``: the restored row of the
transport matrix, where delivery goes through the persisted transport owner or fails closed.

*transport_profile* is what the routing index persisted at ingress (``SessionEntry.transport_profile``);
``None`` = a row written before the column existed, whose transport is unknown â†’ nothing is pinned
and the legacy heuristics (``_is_shared_bot_satellite``) keep deciding. Standalone gateways have
nothing to restore (one bot, one home).
NÚconfigÚmultiplex_profilesF©Úget_profile_dir)Úget_process_hermes_homeÚ_primary_profile_namer#   rU   T©r   r   r   r    r"   r&   )rk   r!   rH   rM   Úhermes_cli.profilesr{   Úhermes_constantsr|   r   Ú _resolve_profile_home_for_sourcer   r   ra   rI   )rE   rn   r   Útransport_nameÚexistingr{   r|   Úprimary_profileÚruntime_namer   r    rL   s   &$$         r   Úrestore_identityr†   ˜   sü   € ô Ð,Ó-€NØÒÙÜ”œ ¨°$Ó7Ð9MÈuÓU×VÒVÙÜ˜6Ó"€HØÒØˆÝ3Ý8äœG FÐ,CÀTÓJÓK×XÐXÈy€OÜœ ¨°DÓ9Ó:×MÐM¸o€Là+9Ô+LŒÑ$Ó&Ô'Ù˜^Ó,ð ð +Ô<ÑÜ�&×9Ñ9¸&ÓAÓBð ð *<Ô&ÜØ(Ø-Ø Dô*€Hô ˆF”N HÔ-Ø€Or   c               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r)   rE   r
   rn   r   r@   r   r;   rl   ro   r*   r   r   )r+   s   "r   r,   r,   À   sF   € ÷ Sñ SØðSØ&)ðSØ47ðSà$ðSà;IðSð ñSr   c          
     ó  € ^ RI Hp ^ RIHpHp \        \        \        VRR4      RR4      4      p\        \        VRR4      4      p	V	f;   \        VRR4      p
\        V
4      '       d   \        V
! 4       4      MR;'       g    R	p	\        V R
R4      pRpVf   VP                  V 4      pVe   Vw  r,M=\        V RR4      f   \        P                  ! V4      V n        VP                  W+4      w  rì\        V4      ;'       g    \        V4      ;'       g    T	pVRJ ;'       d#    \        V4      RJ ;'       d    \        V4      RJ pVe   \        P                  ! V4      MRpV'       g4   \        V! 4       4      p\        W™VVRVR7      p\!        V \"        V4       V# Wù8X  d!   Ve   \        V4      M\        V! 4       4      pM^ RIHp V! V4      pVV n        \        VRV4       R\        V RR4       2p\        V RR4      RJ d   \+        V R24      h\        \        V RR4      4      fE   Wù8X  d   RMTp Vf   VP-                  V 4      MVP-                  V VR7      pT;'       g    TT n        \        V P0                  4      ;'       g    T	pVV8X  d   TM\        VP5                  V 4      4      p\        VVVVRVVR7      p\!        V \"        V4       V#   T d/   pRT n        TP0                  T n        \+        T RT 24      ThRp?ii ; i)aT  Resolve and pin the :class:`RoutingIdentity` of an inbound *source*.

*adapter* is the receiving adapter when the caller holds it; otherwise the source's own
transport provenance is consulted. *transport_profile* names the receiving bot's owning
profile when the caller knows it by construction (the runner's per-profile handlers);
``None`` = derive it from the adapter registry, primary when unknown. *primary_home* is the
primary bot's home for authorization (default: the process home, never a per-turn override).

Stamps ``source.profile`` the way the ingress handlers always did (routed name, else a
secondary's own name; ``None`` stays ``None`` for the primary so the wire is unchanged) and
``_authorization_profile_home`` for the existing authorization readers.

Raises :class:`IdentityUnresolved` under multiplexing when the route is rejected.
)ÚProfileRouteRejected)Úget_hermes_homer|   rx   Nry   Fr}   Ú_active_profile_namer#   Úplatformr   r~   rz   rd   Ú/Úchat_idrh   rQ   Tz: profile route rejectedrU   )Úadapter_profilez: )r   r   r   r    r"   r&   r'   )Úgateway.profile_routingr‰   r€   rŠ   r|   r!   rH   rk   ÚcallableÚ_transport_ownerÚweakrefÚrefr   Ú_owning_profiler   r   ra   rI   r   r{   r   r   Ú_profile_name_for_sourcerQ   rU   rR   r�   )rE   rn   r@   r   rl   r‰   rŠ   r|   r"   r„   ÚactiverŒ   Úowner_profileÚownerÚ_registeredr‚   r'   Útransport_refÚhomerL   r   r{   Úwherer�   Úroutedrt   r…   r    s   &$$$$                       r   rq   rq   À   s  € õ$ =ßIä”wœw v¨x¸Ó>Ð@TÐV[Ó\Ó]€KÜœG FÐ,CÀTÓJÓK€OØÒÜ˜Ð!7¸Ó>ˆÜ.6°v×.>Ò.>œ5¡£œ?ÀD×VÐVÈYˆÜ�v˜z¨4Ó0€Hà#'€MØ‚Ø×'Ñ'¨Ó/ˆØÒØ%*Ñ"ˆGøä�6Ð3°TÓ:ÒBÜ,3¯KªK¸Ó,@ˆFÔ)Ø%+×%;Ñ%;¸GÓ%NÑ"ˆÜÐ,Ó-×XÐX´°}Ó1E×XÐXÈ€NØ  D˜×nÐn¬UÐ3DÓ-EÈÐ-M×nÐnÔRWÐXeÓRfÐjnÐRnÐØ,3Ò,?”G—K’K Ô(ÀT€MçÜ‘OÓ%Ó&ˆÜ"Ø-Ø#°$ÀEÐUbôdˆô 	�œ¨Ô1ØˆàÔ(Ø3?Ò3KœT ,Ô/ÔQUÑVmÓVoÓQpÑå7Ù,¨^Ó<ÐØ);€FÔ&ä�x ¨(Ó3Ð4°A´g¸fÀiÐQSÓ6TÐ5UÐV€EÜˆvÐ/°Ó7¸4Ó?Ü  E 7Ð*BÐ!CÓDÐDÜŒW�V˜Y¨Ó-Ó.Ò6Ø"0Ô"C™$Èˆð	Að <KÒ;R�×/Ñ/°Ô7Ø×4Ñ4°VÈ_Ð4Ó]ð ð  ×2Ð2 ?ˆŒä˜Ÿ™Ó(×;Ð;¨O€Lð +¨nÔ<ÑÜ�&×9Ñ9¸&ÓAÓBð ô Ø(¸,Ø-¸LØ MÐFXôZ€Hô ˆF”N HÔ-Ø€Oøð# $ô 	AØ,0ˆFÔ)Ø-0¯[©[ˆFÔ*Ü$¨ w¨b°°Ð%6Ó7¸SÐ@ûð	Aús   È5(K ËL
Ë)LÌL
zauth:v1:c                ó´  € \        V \        4      '       d   V P                  \        4      '       g   R#  \        P
                  ! V \        \        4      R 4      p\        T\        4      '       dK   \        T4      ^8X  d;   \        ;QJ d    R T 4       F  '       d   K   RM	  RM! R T 4       4      '       g   R# \        T4      #   \         d     R# i ; i)a   ``(provider, issuer, user)`` of an :func:`authenticated_subject` login form
``auth:v1:[provider, issuer, user]``, else None. The one parser for that format: callers
apply their own policy (which logins may be forwarded, which map to a label) to the result.Nc              3  óB   "  € T F  p\        V\        4      x € K  	  R # 5i)N)rJ   r   )Ú.0Úps   & r   Ú	<genexpr>Ú.parse_authenticated_subject.<locals>.<genexpr>#  s   é € Ð?bÑ\aÐWXÄ
È1Ìc×@RÐ@RÓ\aùs   ‚FT)rJ   r   Ú
startswithÚAUTH_SUBJECT_PREFIXÚjsonÚloadsÚlenÚ
ValueErrorÚlistÚallÚtuple)ÚsubjectÚpartss   & r   Úparse_authenticated_subjectr°     s¢   € ô �gœs×#Ò#¨7×+=Ñ+=Ô>Q×+RÒ+RÙðÜ—
’
˜7¤3Ô':Ó#;Ð#<Ð=Ó>ˆô �uœd×#Ò#¬¨E«
°a¬¿C»CÑ?bÑ\aÓ?b¿C¿CºCÑ?bÑ\aÓ?b×<bÒ<bÙÜ�‹<Ðøô	 ô Úðús   µ&C ÃCÃCc                ó–  € \        V P                  R4      ;'       g    R4      pV P                  R4      R8X  d8   V P                  R4      '       d!   V P                  R4      '       d
   RV 9   d   V# \        \        P                  ! V P                  R4      ;'       g    RV P                  R	4      ;'       g    RV.RR
R7      ,           # )a6  Keep private native receipts stable; namespace every dashboard identity.

Only the private bootstrap stamps profile/instance/capabilities. A dashboard
provider named 'local' (or a subject resembling a UID) is not native provenance.
Historical remote bare-subject receipts cannot be assigned to a first caller.
Úuser_idÚunboundÚproviderÚlocalÚ
profile_idÚinstance_idÚcapabilitiesrh   ÚissuerT)Ú
separatorsÚensure_ascii)Ú,Ú:)r   Úgetr¦   r§   Údumps)rL   r®   s   & r   Úauthenticated_subjectrÀ   (  s¢   € ô �(—,‘,˜yÓ)×6Ð6¨YÓ7€GØ�‰�ZÓ  GÔ+°·±¸\×0JÒ0JØ—‘˜]×+Ò+°À(Ô0JØˆÜ¤§¢Ø	�‰�jÓ	!×	'Ð	' R¨¯©°hÓ)?×)EÐ)EÀ2ÀwÐOØ¨Dô"2õ 2ð 2r   )&r   Ú
__future__r   r^   r§   ÚloggingÚ
contextlibr   r“   r   r   Úpathlibr   Útypingr   r   r	   r0   r
   Ú	getLoggerr   rr   rI   r`   ÚRuntimeErrorr   r   rM   rW   rZ   re   rk   ru   r†   rq   r¦   r°   rÀ   r   r   r   Ú<module>rÈ      sõ   ðñõ #ã Û Û Ý Û ß (Ý ß /Ñ /çÝ-à	×	Ò	˜8Ó	$€à€à-Ð/LÈnÐ]Ð ôA˜ô Añ �$Ô÷+Hð +Hó ð+Hõ\Gõ
õaõ	õð
Ø:>ðà'+ðàLP÷õ(%ðPSØ:>ðSà'+ðSàLP÷Sðl !Ð òô2r   