Commit Graph

379 Commits

Author SHA1 Message Date
Christian Gick
f57c91589f fix: Setup SSH before checkout for submodule clone
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m44s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:40:26 +02:00
Christian Gick
5d7cd8731d fix: Add submodule checkout for confluence-collab
Some checks failed
Build & Deploy / build-and-deploy (push) Failing after 5s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:22:48 +02:00
Christian Gick
874ed70d66 feat: Add Gitea Actions deploy workflow (CF-2646)
Some checks failed
Build & Deploy / build-and-deploy (push) Failing after 1m26s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:12:54 +02:00
Christian Gick
ae69ea487c fix: use next_batch as fallback sync token for room_messages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:52:32 +02:00
Christian Gick
e658f3d2ac fix: use room_messages API for /messages endpoint (nio rooms have no timeline attr)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:51:12 +02:00
Christian Gick
8350a0cb1f chore: Trigger rebuild 2026-03-24 16:47:39 +02:00
Christian Gick
b0125bf68e feat: add HTTP API for E2EE Matrix notifications
- POST /notify: send encrypted message to any room
- GET /messages: read decrypted messages from any room
- GET /health: health check
- Authenticated via BOT_API_KEY header
- Port 9100 exposed in docker-compose

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:47:01 +02:00
Christian Gick
b8f62ac38f fix: send bot E2EE key via Olm-encrypted to-device message
Element X only reads encryption keys from encrypted to-device
messages, not room events or call.member state. Bot now sends
its key via Olm-encrypted to-device to all call participants,
matching Element Call's encryptAndSendToDevice behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 12:57:28 +02:00
Christian Gick
776b1af3a0 fix: patch Rust HKDF to output 16 bytes matching Element Call AES-128
Element Call JS SDK derives 128-bit (16-byte) AES-GCM keys via
deriveKey({name:'AES-GCM', length:128}). The C++ FrameCryptor
allocates a larger derived_key buffer, causing Rust HKDF to
output 32+ bytes — key mismatch with JS.

Patch limits HKDF expand output to 16 bytes. Requires Docker
rebuild (Rust FFI binary change).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:29:45 +02:00
Christian Gick
dec6eee726 fix: use default PBKDF2 KDF instead of custom Rust HKDF for E2EE
The custom HKDF=1 path in the Rust FFI fork (EC-compat-changes)
produces different derived keys than the JS SDK's libwebrtc C++.
Switching to PBKDF2=0 lets libwebrtc's built-in C++ FrameCryptor
handle key derivation identically to how the JS SDK does it.

Also aligned ratchet_window_size=0 and key_ring_size=16 to match
Element Call JS SDK defaults (were 10 and 256).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:21:23 +02:00
Christian Gick
621aca19ad fix: handle Element X to-device keys format ({index,key} object, not array)
Element X sends keys as a single dict {index, key} not a list
[{index, key}]. The handler iterated over dict keys ('index','key')
instead of the actual key data. Also extracts device_id from
member.claimed_device_id (Element X format).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 09:58:49 +02:00
Christian Gick
dd904c6928 fix: monkey-patch nio to forward decrypted Olm encryption_keys events
nio's _handle_olm_event silently drops unknown Olm event types
with 'Received unsupported Olm event'. Element X sends E2EE call
keys as encrypted to-device io.element.call.encryption_keys events.
After Olm decryption they were dropped before reaching any callback.

Patch intercepts the drop and forwards to on_to_device_unknown handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 09:55:51 +02:00
Christian Gick
70b0b89290 fix: use actual nio device_id in call.member events, not hardcoded AIBOT
Element X sends E2EE keys via encrypted to-device messages targeting
the device_id from the call.member state event. Bot was advertising
device_id='AIBOT' but its actual Matrix session is on device
'PEYRKFEXFP'. Keys were sent to a non-existent device.

Now uses the real device_id from nio credentials so Element X's
encryptAndSendToDevice reaches the correct device.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 09:38:32 +02:00
Christian Gick
d11516f632 fix: mount Python source files as volumes for hot-reload deploys
git pull + docker compose restart bot now works without --build.
Patched FFI binary and proto bindings stay in the image; only
Python source files are mounted read-only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 09:14:52 +02:00
Christian Gick
c604b5f644 fix: handle Element X to-device encryption key delivery
Element X (26.03.3+) sends io.element.call.encryption_keys as
to-device messages, not room timeline events. Added
UnknownToDeviceEvent callback to catch these and deliver keys
to active voice sessions.

Also added m.room.encrypted decryption attempt in timeline scan
as fallback for older Element versions that send encrypted timeline
events.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 09:08:09 +02:00
Christian Gick
c11dd73ce3 fix: handle Element X MSC4143 v2 encryption key format (memberships array)
Element X embeds E2EE keys inside memberships[].encryption_keys,
not at the top level of the call.member state event content.
Bot was only checking content.encryption_keys, so it never found
the caller's key — causing 'Warten auf Medien' (waiting for media)
because encrypted audio couldn't be decrypted.

- Added _extract_enc_keys_from_content() helper handling both formats
- Updated on_unknown handler, VoiceSession creation, and key fetch
- Bot now publishes keys in both formats for compatibility
- Updated voice.py state fetch to check memberships[] fallback

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 08:57:24 +02:00
Christian Gick
3363b4238f chore: Trigger rebuild 2026-03-24 08:40:30 +02:00
Christian Gick
fafd440506 chore: Trigger rebuild 2026-03-24 08:30:51 +02:00
Christian Gick
0ae59c8ebe feat(CF-2411): Pipeline hardening — Sentry, retry, concurrent limits, audit log
- Sentry transactions wrapping pipeline execution with tags
- Retry with exponential backoff for transient failures (connect, timeout, 5xx)
- Concurrent execution limit (3/user) enforced in scheduler
- Audit log events fired at each pipeline lifecycle point
- Resume support: skip already-completed steps on restart

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 08:29:24 +02:00
Christian Gick
b3e6ae65de fix: URL-encode user_id in Synapse admin API paths
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:11:19 +02:00
Christian Gick
07d781d101 chore: Trigger rebuild 2026-03-23 19:06:36 +02:00
Christian Gick
7fd3aae176 feat(CF-2502): proper E2E encryption with cross-signing and device lifecycle
Replace insecure auto-trust-all-devices with cross-signed-only trust policy.
Extract cross-signing manager into reusable module with vault backup/recovery.
Add device cleanup script and automatic old device pruning on startup.

- device_trust.py: CrossSignedOnlyPolicy (only trust cross-signed devices)
- cross_signing.py: Extracted from bot.py, adds vault seed backup + recovery
- scripts/matrix_device_cleanup.py: Synapse Admin API bulk device cleanup CLI
- bot.py: Use new modules, add _cleanup_own_devices() on startup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:05:48 +02:00
Christian Gick
bfc717372c fix(voice): add MSC4143 call.member encryption key support
Element Call v0.17+ embeds encryption_keys in call.member state events
instead of separate timeline events. In E2EE rooms, timeline events are
encrypted and the bot HTTP fetch cannot decrypt them, causing DEC_FAILED.

- Extract caller keys from call.member state event on join
- Embed bot key in call.member state event
- Check call.member state in key fetch (before timeline fallback)
- Handle key updates in call.member during active calls
- Update voice.py key poller to check call.member state first
- Add debug logging for UnknownEvent types in call rooms

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 08:12:58 +02:00
Christian Gick
dcee2d30d5 fix: silently cache images in group rooms without mention
Same pattern as files: download and cache in _recent_images without
responding. When user next @mentions the bot, the cached image is
available as context. Applied to both plain and encrypted image handlers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 15:42:13 +00:00
Christian Gick
cb5f057006 fix: silently ingest files in group rooms without mention
Files uploaded to group rooms are now downloaded, parsed, and stored
in _room_document_context even without @mention. When the user later
mentions the bot, the document context is automatically included.

Previously files were silently dropped if the caption didn't contain
a mention, so the bot would say it can't access uploaded PDFs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 15:24:52 +00:00
Christian Gick
b69980d57f fix: match display name ('Claude') in group room mention check
Bot user is @ai:agiliton.eu but display name is 'Claude'.
Element renders mentions using display name, so the old check
for 'ai' in message body never matched '@Claude: ...' messages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 15:05:22 +00:00
Christian Gick
0988f636d0 feat: add pitrader_script step type + image vision for pipeline triggers
Add pitrader_script executor for running PITrader scripts (pi-scan,
playbook, execute_trades) as pipeline steps with vault credential
injection and JSON output capture.

Extend claude_prompt step with vision support (image_b64 in trigger
context). Add image pipeline trigger to on_image_message handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:45:36 +02:00
Christian Gick
18b88d490f chore: Trigger rebuild 2026-03-19 12:36:23 +02:00
Christian Gick
c29c2170f3 fix(e2ee): fix screen share key rotation failures (MAT-164)
- Route HTTP-fetched keys through on_encryption_key() for proper rotation detection
- Replace boolean refetch gate with 500ms timestamp throttle for faster recovery
- Reduce DEC_FAILED cooldown from 2s to 0.5s
- Extend proactive key poll from 3s to 10s window
- Add continuous background key poller (3s interval) during active calls

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:35:50 +02:00
Christian Gick
183c41a72b chore: Trigger rebuild 2026-03-19 11:01:40 +02:00
Christian Gick
6ee3e74b1d feat: format Agent results as readable markdown list
Renders extracted items as markdown links with details instead of
raw JSON. Handles common patterns: list of dicts with title/link.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 11:01:18 +02:00
Christian Gick
b4425fc9e9 chore: Trigger rebuild 2026-03-19 10:41:27 +02:00
Christian Gick
006ed48cbe fix: prevent re-triggering pending jobs while already running
Track running job IDs to avoid creating duplicate Skyvern tasks
when the pending check runs faster than the task completes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 10:41:07 +02:00
Christian Gick
909c128a65 chore: Trigger rebuild 2026-03-19 10:18:45 +02:00
Christian Gick
a0b410337a chore: Trigger rebuild 2026-03-19 10:13:29 +02:00
Christian Gick
ad2caa90e7 chore: Trigger rebuild 2026-03-19 10:11:06 +02:00
Christian Gick
9f6132654c chore: Trigger rebuild 2026-03-19 10:10:09 +02:00
Christian Gick
6b226acb13 chore: Trigger rebuild 2026-03-19 10:09:22 +02:00
Christian Gick
9a223cd305 chore: Trigger rebuild 2026-03-19 10:08:30 +02:00
Christian Gick
21b6e78e83 chore: Trigger rebuild 2026-03-19 10:07:39 +02:00
Christian Gick
1d7730fbf7 fix: increase httpx timeout to 60s for Skyvern API calls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 10:07:20 +02:00
Christian Gick
3aac724627 chore: Trigger rebuild 2026-03-19 10:01:16 +02:00
Christian Gick
ac0aefcfeb fix: use navigation_goal/data_extraction_goal for self-hosted Skyvern API
Cloud API uses 'prompt', self-hosted uses 'navigation_goal' and
'data_extraction_goal'. Pass them separately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 10:00:56 +02:00
Christian Gick
8862ed2596 chore: Trigger rebuild 2026-03-19 09:23:26 +02:00
Christian Gick
8970179493 fix: remove /v1 suffix from OPENAI_COMPATIBLE_API_BASE
litellm client appends /v1/chat/completions itself.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:23:07 +02:00
Christian Gick
6084cd7d45 chore: Trigger rebuild 2026-03-19 09:20:37 +02:00
Christian Gick
ae8e6d7658 fix: use OPENAI_COMPATIBLE provider for Skyvern LLM via LiteLLM proxy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:20:19 +02:00
Christian Gick
5f3b8ef1d8 chore: Trigger rebuild 2026-03-19 08:48:38 +02:00
Christian Gick
d86401fe93 feat: support extractionGoal from portal in browser executor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 08:48:11 +02:00
Christian Gick
ea0df8c223 chore: Trigger rebuild 2026-03-19 08:41:30 +02:00