lex-microsoft_teams 0.5.4 → 0.5.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 050cf6a6703c4b6ee4d636980ee7843a3bc34b27c533d0d1cab0325c9903ca02
4
- data.tar.gz: ffb0ca49267fc2f64b1a27c10f25e45099e2d2450839b3ddf8984efe21572d6b
3
+ metadata.gz: 5dd2ecc48c7eda33072b23d32d9a08947b43d51aaeba49b6b4eb46fb410e8065
4
+ data.tar.gz: ec8b561ede2e96afe790aad56ecc02c3491117ea26e3bbd2e78a480d214a58d2
5
5
  SHA512:
6
- metadata.gz: 9f93cdb1ff43c5ff3829f71de8aedca04086cf1a8efed385441a8d0920d39c7a429718e3de6035f734021921d3583ed2004648dc97bd47982cb75d6258baebc7
7
- data.tar.gz: 50327854fc1dad382f923be114d6b2c413666070f2e8cffb14c35cd467d73519654bdc7bb372fb370ed743e834d438ea4ce25663b7826c0f56a0f6bdd1b6953f
6
+ metadata.gz: 786b4d6f2b4e3cce9fee5d61d96cb2c89f31080628d19c5e146976e9eaf3ecb6e4e8eaf76854493cfa37e6dba89721c0e6dca42e8dd657bbaac67ad84b195cf6
7
+ data.tar.gz: 82fc1cf2c2f31b81e7f640b5edc00be53cc976733bb7c33f3d3a68648991ad0a6979cfb2eb43f57584c48aeb7dd90542ac787e056fc44938216b7b7b9bbed41a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.5] - 2026-03-19
4
+
5
+ ### Added
6
+ - `Hooks::Auth` hook class with `mount '/callback'` for OAuth redirect via expanded hooks system
7
+ - `Runners::Auth#auth_callback` method handling OAuth callback with HTML response and event emission
8
+ - OAuth callback now routes through `Ingress.run` for RBAC and audit support
9
+
10
+ ### Changed
11
+ - OAuth callback URL moves from hardcoded `/api/oauth/microsoft_teams/callback` to `/api/hooks/lex/microsoft_teams/auth/callback`
12
+
3
13
  ## [0.5.4] - 2026-03-19
4
14
 
5
15
  ### Added
data/CLAUDE.md CHANGED
@@ -10,7 +10,7 @@ Legion Extension that connects LegionIO to Microsoft Teams via Graph API and Bot
10
10
 
11
11
  **GitHub**: https://github.com/LegionIO/lex-microsoft_teams
12
12
  **License**: MIT
13
- **Version**: 0.5.2
13
+ **Version**: 0.5.4
14
14
 
15
15
  ## Architecture
16
16
 
@@ -36,7 +36,9 @@ Legion::Extensions::MicrosoftTeams
36
36
  │ ├── CacheSync # Every 5min: incremental ingest of new messages
37
37
  │ ├── DirectChatPoller # Every 5s: polls bot DM chats via Graph API
38
38
  │ ├── ObservedChatPoller # Every 30s: polls subscribed human conversations (compliance-gated)
39
- └── MessageProcessor # Subscription: consumes AMQP queue, routes by mode
39
+ ├── MessageProcessor # Subscription: consumes AMQP queue, routes by mode
40
+ │ ├── AuthValidator # Once: validates/restores delegated tokens on boot (2s delay)
41
+ │ └── TokenRefresher # Every 15min (configurable): keeps delegated tokens fresh
40
42
  ├── Transport/
41
43
  │ ├── Exchanges/Messages # teams.messages topic exchange
42
44
  │ ├── Queues/MessagesProcess # teams.messages.process durable queue
@@ -50,7 +52,7 @@ Legion::Extensions::MicrosoftTeams
50
52
  │ ├── HighWaterMark # Per-chat message dedup via legion-cache (with in-memory fallback)
51
53
  │ ├── PromptResolver # Layered system prompt resolution (settings -> mode -> per-conversation)
52
54
  │ ├── SessionManager # Multi-turn LLM session lifecycle with lex-memory persistence
53
- │ ├── TokenCache # In-memory OAuth token cache with pre-expiry refresh (app + delegated slots)
55
+ │ ├── TokenCache # In-memory OAuth token cache with pre-expiry refresh (app + delegated slots, authenticated?/previously_authenticated? predicates)
54
56
  │ ├── SubscriptionRegistry # Conversation observation subscriptions (in-memory + lex-memory)
55
57
  │ ├── BrowserAuth # Delegated OAuth orchestrator (PKCE, headless detection, browser launch)
56
58
  │ └── CallbackServer # Ephemeral TCP server for OAuth redirect callback
@@ -68,6 +70,18 @@ Tokens stored in Vault (`legionio/microsoft_teams/delegated_token`) with configu
68
70
 
69
71
  Key files: `Helpers::BrowserAuth` (orchestrator), `Helpers::CallbackServer` (ephemeral TCP), `Runners::Auth` (authorize_url, exchange_code, refresh_delegated_token), `Helpers::TokenCache` (delegated slot).
70
72
 
73
+ ## Token Lifecycle (v0.5.4)
74
+
75
+ Automatic delegated token management: validate on boot, refresh on a timer, re-authenticate via browser when a previously authenticated user's token expires.
76
+
77
+ - **AuthValidator** (Once actor, 2s delay): Loads token from Vault/local file on boot, attempts refresh. If refresh fails and user previously authenticated (`previously_authenticated?` — local file exists), fires BrowserAuth. Silent for users who never opted in.
78
+ - **TokenRefresher** (Every actor, 15min default): Guards with `authenticated?` (live token in memory). Refreshes and persists on each tick. On failure, same re-auth logic as AuthValidator.
79
+ - **TokenCache predicates**: `authenticated?` = live token in `@delegated_cache`. `previously_authenticated?` = local token file exists on disk. This distinction controls auto re-auth (returning users only) vs silence (never-authenticated users).
80
+
81
+ Configuration: `settings[:microsoft_teams][:auth][:delegated][:refresh_interval]` (default 900 seconds).
82
+
83
+ Design doc: `docs/plans/2026-03-19-teams-token-lifecycle-design.md`
84
+
71
85
  ## AI Bot (v0.2.0)
72
86
 
73
87
  Two operating modes, both using polling (Graph API) with AMQP-based message routing:
@@ -104,6 +118,8 @@ microsoft_teams:
104
118
  tenant_id: "..."
105
119
  client_id: "..."
106
120
  client_secret: "vault://secret/teams/client_secret"
121
+ delegated:
122
+ refresh_interval: 900 # seconds (TokenRefresher interval)
107
123
  bot:
108
124
  bot_id: "28:your-bot-id"
109
125
  direct_poll_interval: 5 # seconds
@@ -197,7 +213,7 @@ Optional framework dependencies (guarded with `defined?`, not in gemspec):
197
213
 
198
214
  ```bash
199
215
  bundle install
200
- bundle exec rspec # 185 specs (as of v0.5.2)
216
+ bundle exec rspec # 209 specs (as of v0.5.4)
201
217
  bundle exec rubocop # Clean
202
218
  ```
203
219
 
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module MicrosoftTeams
6
+ module Hooks
7
+ class Auth < Legion::Extensions::Hooks::Base
8
+ mount '/callback'
9
+
10
+ def route(_headers, _payload)
11
+ :auth_callback
12
+ end
13
+
14
+ def runner_class
15
+ 'Legion::Extensions::MicrosoftTeams::Runners::Auth'
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -107,6 +107,35 @@ module Legion
107
107
  { result: response.body }
108
108
  end
109
109
 
110
+ def auth_callback(code: nil, state: nil, **)
111
+ unless code && state
112
+ return {
113
+ result: { error: 'missing_params' },
114
+ response: { status: 400, content_type: 'text/html',
115
+ body: '<html><body><h2>Missing code or state parameter</h2></body></html>' }
116
+ }
117
+ end
118
+
119
+ Legion::Events.emit('microsoft_teams.oauth.callback', code: code, state: state) if defined?(Legion::Events)
120
+
121
+ {
122
+ result: { authenticated: true, code: code, state: state },
123
+ response: { status: 200, content_type: 'text/html',
124
+ body: callback_success_html }
125
+ }
126
+ end
127
+
128
+ private
129
+
130
+ def callback_success_html
131
+ <<~HTML
132
+ <html><body style="font-family:sans-serif;text-align:center;padding:40px;">
133
+ <h2>Authentication complete</h2>
134
+ <p>You can close this window.</p>
135
+ </body></html>
136
+ HTML
137
+ end
138
+
110
139
  include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
111
140
  Legion::Extensions::Helpers.const_defined?(:Lex)
112
141
  end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module MicrosoftTeams
6
- VERSION = '0.5.4'
6
+ VERSION = '0.5.5'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-microsoft_teams
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -91,6 +91,7 @@ files:
91
91
  - lib/legion/extensions/microsoft_teams/helpers/session_manager.rb
92
92
  - lib/legion/extensions/microsoft_teams/helpers/subscription_registry.rb
93
93
  - lib/legion/extensions/microsoft_teams/helpers/token_cache.rb
94
+ - lib/legion/extensions/microsoft_teams/hooks/auth.rb
94
95
  - lib/legion/extensions/microsoft_teams/local_cache/extractor.rb
95
96
  - lib/legion/extensions/microsoft_teams/local_cache/record_parser.rb
96
97
  - lib/legion/extensions/microsoft_teams/local_cache/sstable_reader.rb