From d4ce94ddf83145b6c0ffdfc226ef177c74273cd1 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 17 Dec 2025 14:53:13 +0100 Subject: [PATCH 01/38] Split/merge WIP --- ...bridge-ticket-split-merge-investigation.md | 506 ++++++++++ docs/ticket-field-propagation-design.md | 906 ++++++++++++++++++ 2 files changed, 1412 insertions(+) create mode 100644 docs/bridge-ticket-split-merge-investigation.md create mode 100644 docs/ticket-field-propagation-design.md diff --git a/docs/bridge-ticket-split-merge-investigation.md b/docs/bridge-ticket-split-merge-investigation.md new file mode 100644 index 0000000..ebf48b3 --- /dev/null +++ b/docs/bridge-ticket-split-merge-investigation.md @@ -0,0 +1,506 @@ +# Zammad Ticket Splits & Merges with Bridge Channels + +## Investigation Summary + +This document analyzes how Zammad handles ticket splits and merges, and the implications for our custom bridge channels (WhatsApp, Signal, Voice). + +## Current State + +### How Zammad Handles Split/Merge (Built-in) + +#### Merge (`ticket.merge_to` in `app/models/ticket.rb:330`) + +When ticket A is merged into ticket B: + +1. All articles from A are moved to B +2. A "parent" link is created between A and B +3. Mentions and external links are migrated +4. Source ticket A's state is set to "merged" +5. Source ticket A's owner is reset to System (id: 1) + +**Critical issue:** Ticket preferences are NOT copied or migrated. The target ticket B keeps its original preferences, and source ticket A's preferences become orphaned. + +```ruby +# From app/models/ticket.rb - merge_to method +# Articles are moved: +Ticket::Article.where(ticket_id: id).update_all(['ticket_id = ?', data[:ticket_id]]) + +# But preferences are never touched - they stay on the source ticket +``` + +#### Split (`app/models/form_updater/concerns/applies_split_ticket_article.rb`) + +When an article is split from ticket A to create new ticket C: + +1. Basic ticket attributes are copied (group, customer, state, priority, title) +2. Attachments are cloned +3. A link is created to the original ticket +4. `owner_id` is explicitly deleted (not copied) + +**Critical issue:** Preferences are NOT copied. The new ticket C has no channel metadata. + +```ruby +# From applies_split_ticket_article.rb +def attributes_to_apply + attrs = selected_ticket_article.ticket.attributes + attrs['title'] = selected_ticket_article.subject if selected_ticket_article.subject.present? + attrs['body'] = body_with_form_id_urls + attrs.delete 'owner_id' # Explicitly deleted + attrs + # Note: preferences are NOT included in .attributes +end +``` + +#### Email Follow-up Handling (`app/models/channel/filter/follow_up_merged.rb`) + +Zammad has a postmaster filter that handles incoming emails to merged tickets: + +```ruby +def self.run(_channel, mail, _transaction_params) + return if mail[:'x-zammad-ticket-id'].blank? + + referenced_ticket = Ticket.find_by(id: mail[:'x-zammad-ticket-id']) + return if referenced_ticket.blank? + + new_target_ticket = find_merge_follow_up_ticket(referenced_ticket) + return if new_target_ticket.blank? + + mail[:'x-zammad-ticket-id'] = new_target_ticket.id +end +``` + +This follows the parent link to find the active target ticket. **This only works for email** - no equivalent exists for other channels like Telegram, WhatsApp, or Signal. + +--- + +## Bridge Channel Metadata Structure + +Our bridge channels store critical routing metadata in `ticket.preferences`: + +### WhatsApp + +```ruby +ticket.preferences = { + channel_id: 123, + cdr_whatsapp: { + bot_token: "abc123", # Identifies which bot/channel + chat_id: "+1234567890" # Customer's phone number - WHERE TO SEND + } +} +``` + +### Signal (Direct Message) + +```ruby +ticket.preferences = { + channel_id: 456, + cdr_signal: { + bot_token: "xyz789", + chat_id: "+1234567890" # Customer's phone number + } +} +``` + +### Signal (Group) + +```ruby +ticket.preferences = { + channel_id: 456, + cdr_signal: { + bot_token: "xyz789", + chat_id: "group.abc123...", # Signal group ID + group_joined: true, # Whether customer accepted invite + group_joined_at: "2024-01-01", + original_recipient: "+1234567890" + } +} +``` + +--- + +## How Bridge Channels Use This Metadata + +### Outgoing Messages + +The communication jobs (`CommunicateCdrWhatsappJob`, `CommunicateCdrSignalJob`) rely entirely on ticket preferences: + +```ruby +# From communicate_cdr_whatsapp_job.rb +def perform(article_id) + article = Ticket::Article.find(article_id) + ticket = Ticket.lookup(id: article.ticket_id) + + # These MUST exist or the job fails: + unless ticket.preferences['cdr_whatsapp']['bot_token'] + log_error(article, "Can't find ticket.preferences['cdr_whatsapp']['bot_token']") + end + unless ticket.preferences['cdr_whatsapp']['chat_id'] + log_error(article, "Can't find ticket.preferences['cdr_whatsapp']['chat_id']") + end + + channel = Channel.lookup(id: ticket.preferences['channel_id']) + result = channel.deliver(article) # Uses chat_id to know where to send +end +``` + +### Incoming Messages + +The webhook controllers look up existing tickets: + +**WhatsApp** (`channels_cdr_whatsapp_controller.rb`): +```ruby +# Find open ticket for this customer +state_ids = Ticket::State.where(name: %w[closed merged removed]).pluck(:id) +ticket = Ticket.where(customer_id: customer.id) + .where.not(state_id: state_ids) + .order(:updated_at).first +``` + +**Signal Groups** (`channels_cdr_signal_controller.rb`): +```ruby +# Find ticket by group ID in preferences +ticket = Ticket.where.not(state_id: state_ids) + .where("preferences LIKE ?", "%channel_id: #{channel.id}%") + .where("preferences LIKE ?", "%chat_id: #{receiver_phone_number}%") + .order(updated_at: :desc) + .first +``` + +--- + +## Problem Scenarios + +### Scenario 1: Merge Bridge Ticket → Non-Bridge Ticket + +**Setup:** Ticket A (has WhatsApp metadata) merged into Ticket B (no bridge metadata) + +**What happens:** +- A's articles move to B +- A's preferences stay on A (now in merged state) +- B still has no bridge preferences + +**Result:** Agent replies on ticket B fail - no `chat_id` to send to. + +### Scenario 2: Merge Bridge Ticket → Different Bridge Ticket + +**Setup:** Ticket A (WhatsApp to +111) merged into Ticket B (WhatsApp to +222) + +**What happens:** +- A's articles move to B +- B keeps its preferences (`chat_id: +222`) + +**Result:** Agent replies go to +222, not to +111. Customer +111 never receives responses. + +### Scenario 3: Split Article from Bridge Ticket + +**Setup:** Split an article from Ticket A (has WhatsApp metadata) to create Ticket C + +**What happens:** +- New ticket C is created with no preferences +- C is linked to A + +**Result:** Agent cannot reply via WhatsApp on ticket C at all - job fails immediately. + +### Scenario 4: Incoming Message to Merged Ticket's Customer + +**Setup:** Ticket A (customer +111) was merged into B. Customer +111 sends new message. + +**What happens:** +- Webhook finds customer by phone number +- Looks for open ticket for customer +- A is excluded (merged state) +- Either finds B (if same customer) or creates new ticket + +**Result:** May work if B has same customer, but conversation context is fragmented. + +### Scenario 5: Signal Group Ticket Merged + +**Setup:** Ticket A (Signal group X) merged into Ticket B (no Signal metadata) + +**What happens:** +- All group messages went to A +- A is now merged, B has no group reference +- New messages from group X create a new ticket (can't find existing by group ID) + +**Result:** Conversation splits into multiple tickets unexpectedly. + +--- + +## Recommended Solutions + +### Option 1: Preferences Migration on Merge (Recommended) + +Create a concern that copies bridge channel metadata when tickets are merged: + +```ruby +# app/models/ticket/merge_bridge_channel_preferences.rb +module Ticket::MergeBridgeChannelPreferences + extend ActiveSupport::Concern + + included do + after_update :migrate_bridge_preferences_on_merge + end + + private + + def migrate_bridge_preferences_on_merge + return unless saved_change_to_state_id? + return unless state.state_type.name == 'merged' + + target_ticket = find_merge_target + return unless target_ticket + + # Copy bridge preferences if target doesn't have them + %w[cdr_whatsapp cdr_signal cdr_voice].each do |channel_key| + next unless preferences[channel_key].present? + next if target_ticket.preferences[channel_key].present? + + target_ticket.preferences[channel_key] = preferences[channel_key].deep_dup + target_ticket.preferences['channel_id'] ||= preferences['channel_id'] + end + + target_ticket.save! if target_ticket.changed? + end + + def find_merge_target + Link.list(link_object: 'Ticket', link_object_value: id) + .find { |l| l['link_type'] == 'parent' && l['link_object'] == 'Ticket' } + &.then { |l| Ticket.find_by(id: l['link_object_value']) } + end +end +``` + +**Pros:** +- Handles the common case (merging bridge ticket into non-bridge ticket) +- Automatic, no agent action required +- Non-destructive (doesn't overwrite existing preferences) + +**Cons:** +- Doesn't handle case where both tickets have different bridge metadata +- May need additional logic for conflicting preferences + +### Option 2: Follow-up Filter for Bridge Channels + +Create filters similar to `FollowUpMerged` that redirect incoming bridge messages: + +```ruby +# Modify webhook controllers to check for merged tickets +def find_active_ticket_for_customer(customer, state_ids) + ticket = Ticket.where(customer_id: customer.id) + .where.not(state_id: state_ids) + .order(:updated_at).first + + # If ticket is merged, follow parent link + if ticket&.state&.state_type&.name == 'merged' + ticket = find_merge_target(ticket) || ticket + end + + ticket +end + +def find_merge_target(ticket) + Link.list(link_object: 'Ticket', link_object_value: ticket.id) + .filter_map do |link| + next if link['link_type'] != 'parent' + next if link['link_object'] != 'Ticket' + + Ticket.joins(state: :state_type) + .where.not(ticket_state_types: { name: 'merged' }) + .find_by(id: link['link_object_value']) + end.first +end +``` + +**Pros:** +- Handles incoming messages to merged tickets correctly +- Follows same pattern as Zammad's email handling + +**Cons:** +- Requires modifying webhook controllers +- Only handles incoming direction, not outgoing + +### Option 3: Copy Preferences on Split + +Modify the split form updater or add a callback to copy bridge preferences: + +```ruby +# Add to ticket creation from split +module Ticket::SplitBridgeChannelPreferences + extend ActiveSupport::Concern + + included do + after_create :copy_bridge_preferences_from_source + end + + private + + def copy_bridge_preferences_from_source + # Find source ticket via link + source_link = Link.list(link_object: 'Ticket', link_object_value: id) + .find { |l| l['link_type'] == 'child' } + return unless source_link + + source_ticket = Ticket.find_by(id: source_link['link_object_value']) + return unless source_ticket + + # Copy bridge preferences + %w[cdr_whatsapp cdr_signal cdr_voice channel_id].each do |key| + next unless source_ticket.preferences[key].present? + self.preferences[key] = source_ticket.preferences[key].deep_dup + end + + save! if changed? + end +end +``` + +### Option 4: UI Warning + Manual Handling + +Add frontend validation to warn agents: + +1. Check for bridge preferences before merge/split +2. Show warning dialog explaining implications +3. Optionally provide UI to manually transfer channel association + +```typescript +// In merge confirmation dialog +const hasBridgeChannel = ticket.preferences?.cdr_whatsapp || + ticket.preferences?.cdr_signal; +if (hasBridgeChannel) { + showWarning( + "This ticket uses WhatsApp/Signal messaging. " + + "Merging may affect message routing. " + + "Replies will be sent to the target ticket's contact." + ); +} +``` + +### Option 5: Multi-Channel Preferences (Long-term) + +Allow tickets to have multiple channel associations: + +```ruby +ticket.preferences = { + bridge_channels: [ + { type: 'cdr_whatsapp', chat_id: '+111...', channel_id: 1, customer_id: 100 }, + { type: 'cdr_whatsapp', chat_id: '+222...', channel_id: 1, customer_id: 101 }, + { type: 'cdr_signal', chat_id: 'group.xxx', channel_id: 2 } + ] +} +``` + +This would require significant refactoring of communication jobs to handle multiple recipients. + +--- + +## Signal Groups - Special Considerations + +Signal groups add complexity: + +1. **Group ID is the routing key**, not phone number +2. **Multiple customers** might be in the same group +3. **`group_joined` flag** tracks invite acceptance - messages can't be sent until true +4. **Group membership changes** could affect ticket routing + +### Merge Rules for Signal Groups + +| Source Ticket | Target Ticket | Recommendation | +|---------------|---------------|----------------| +| Signal group A | No Signal | Copy preferences (Option 1) | +| Signal group A | Signal group A (same) | Safe to merge | +| Signal group A | Signal group B (different) | **Block or warn** - can't merge different group conversations | +| Signal group A | Signal DM | **Block or warn** - different communication modes | + +Consider adding validation: + +```ruby +def validate_signal_group_merge(source, target) + source_group = source.preferences.dig('cdr_signal', 'chat_id') + target_group = target.preferences.dig('cdr_signal', 'chat_id') + + return true if source_group.blank? || target_group.blank? + return true if source_group == target_group + + # Different groups - this is problematic + raise Exceptions::UnprocessableEntity, + "Cannot merge tickets from different Signal groups" +end +``` + +--- + +## Recommended Implementation Path + +### Phase 1: Immediate (Low Risk) + +1. **Add preferences migration on merge** (Option 1) + - Only copies if target doesn't have existing preferences + - Handles most common case safely + +2. **Add preferences copy on split** (Option 3) + - New tickets get parent's channel metadata + - Enables replies on split tickets + +### Phase 2: Short-term + +3. **Add follow-up handling in webhooks** (Option 2) + - Modify webhook controllers to follow merge parent links + - Handles incoming messages to merged ticket's customer + +4. **Add UI warnings** (Option 4) + - Warn agents about implications + - Especially for conflicting metadata scenarios + +### Phase 3: Medium-term + +5. **Add merge validation for Signal groups** + - Block merging tickets from different groups + - Or add clear warning about implications + +6. **Add audit logging** + - Track when preferences are migrated + - Help agents understand what happened + +--- + +## Files to Modify + +### Zammad Addon (zammad-addon-bridge) + +| File | Change | +|------|--------| +| `src/app/models/ticket/merge_bridge_channel_preferences.rb` | New - preferences migration | +| `src/app/models/ticket/split_bridge_channel_preferences.rb` | New - preferences copy on split | +| `src/app/controllers/channels_cdr_whatsapp_controller.rb` | Add merge follow-up handling | +| `src/app/controllers/channels_cdr_signal_controller.rb` | Add merge follow-up handling | +| `src/config/initializers/bridge.rb` | Include new concerns in Ticket model | + +### Link Frontend (optional) + +| File | Change | +|------|--------| +| Merge dialog component | Add warning for bridge tickets | + +--- + +## Testing Scenarios + +1. Merge WhatsApp ticket → empty ticket → verify agent can reply +2. Merge WhatsApp ticket → WhatsApp ticket (same number) → verify routing +3. Merge WhatsApp ticket → WhatsApp ticket (different number) → verify warning/behavior +4. Split article from WhatsApp ticket → verify new ticket has preferences +5. Customer sends message after their ticket was merged → verify routing +6. Merge Signal group ticket → verify group_joined flag is preserved +7. Merge two different Signal group tickets → verify validation/warning + +--- + +## References + +- Zammad merge implementation: `app/models/ticket.rb:330-450` +- Zammad split implementation: `app/models/form_updater/concerns/applies_split_ticket_article.rb` +- Zammad email follow-up filter: `app/models/channel/filter/follow_up_merged.rb` +- Bridge WhatsApp controller: `packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb` +- Bridge Signal controller: `packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb` +- Bridge WhatsApp job: `packages/zammad-addon-bridge/src/app/jobs/communicate_cdr_whatsapp_job.rb` +- Bridge Signal job: `packages/zammad-addon-bridge/src/app/jobs/communicate_cdr_signal_job.rb` diff --git a/docs/ticket-field-propagation-design.md b/docs/ticket-field-propagation-design.md new file mode 100644 index 0000000..61d4bec --- /dev/null +++ b/docs/ticket-field-propagation-design.md @@ -0,0 +1,906 @@ +# Ticket Field Propagation System + +## Overview + +A configurable system for copying/syncing fields between related tickets (parent/child, merged, linked). This addresses the bridge channel preferences problem while providing a general-purpose solution for custom fields. + +## Problem Statement + +Zammad creates relationships between tickets through: +- **Split**: Creates child ticket from parent's article +- **Merge**: Source ticket becomes child of target (merged state) +- **Manual linking**: Agents can link tickets as parent/child or related + +Currently, no field values are propagated across these relationships except basic attributes on split. This causes issues when: +- Bridge channel metadata needs to follow the conversation +- Custom fields (account ID, region, priority score) should be inherited +- Parent ticket context should flow to children (or vice versa) + +## Use Cases + +### Use Case 1: Bridge Channel Inheritance (Immediate Need) +When a ticket is split or merged, the bridge channel metadata (`preferences.cdr_whatsapp`, `preferences.cdr_signal`) should be copied so agents can reply via the same channel. + +### Use Case 2: Custom Field Inheritance +Organization uses custom fields like `account_tier`, `region`, `contract_id`. When splitting a ticket, the child should inherit these values. + +### Use Case 3: Escalation Propagation +When a child ticket is escalated (custom `escalation_level` field), the parent should be updated to reflect this. + +### Use Case 4: SLA Context +Parent ticket has SLA deadline. Child tickets should inherit or reference this deadline. + +### Use Case 5: Bulk Operations +When updating a parent ticket's category, optionally cascade to all children. + +--- + +## Design + +### Terminology + +| Term | Definition | +|------|------------| +| **Source** | The ticket providing the field value | +| **Target** | The ticket receiving the field value | +| **Direction** | Which way data flows (parent→child, child→parent, source→target on merge) | +| **Trigger** | The event that initiates propagation (split, merge, update, link_create) | +| **Condition** | When to apply the copy (always, if_empty, if_greater, custom) | +| **Field Path** | Dot-notation path to the field (`preferences.cdr_whatsapp.chat_id`) | + +### Field Types + +The system must handle different field storage mechanisms: + +```ruby +# 1. Standard ticket attributes +ticket.group_id +ticket.priority_id +ticket.organization_id + +# 2. Preferences hash (nested) +ticket.preferences['channel_id'] +ticket.preferences['cdr_whatsapp']['chat_id'] +ticket.preferences['cdr_signal']['group_joined'] + +# 3. Custom object attributes (Zammad ObjectManager) +ticket.custom_account_id # Added via Admin → Objects → Ticket +ticket.custom_region +ticket.custom_escalation_level + +# 4. Tags (special handling) +ticket.tag_list # Array of strings +``` + +### Configuration Schema + +```ruby +# Stored in Setting or dedicated table +TicketFieldPropagation.configure do |config| + + # Define field groups for convenience + config.field_group :bridge_channel, [ + 'preferences.channel_id', + 'preferences.cdr_whatsapp', # Copies entire hash + 'preferences.cdr_signal', + 'preferences.cdr_voice' + ] + + config.field_group :customer_context, [ + 'organization_id', + 'custom_account_id', + 'custom_region', + 'custom_contract_id' + ] + + config.field_group :sla_context, [ + 'custom_sla_deadline', + 'custom_escalation_level' + ] + + # Define propagation rules + + # Bridge preferences: copy to child on split if child doesn't have them + config.rule :bridge_on_split do |r| + r.fields :bridge_channel + r.trigger :split + r.direction :parent_to_child + r.condition :if_target_empty + r.timing :immediate + end + + # Bridge preferences: copy to target on merge if target doesn't have them + config.rule :bridge_on_merge do |r| + r.fields :bridge_channel + r.trigger :merge + r.direction :source_to_target + r.condition :if_target_empty + r.timing :immediate + end + + # Customer context: always copy to child on split + config.rule :customer_context_on_split do |r| + r.fields :customer_context + r.trigger :split + r.direction :parent_to_child + r.condition :always + r.timing :immediate + end + + # Escalation: propagate highest level to parent + config.rule :escalation_to_parent do |r| + r.fields ['custom_escalation_level'] + r.trigger :update + r.direction :child_to_parent + r.condition :if_greater + r.timing :deferred # Use job queue + end + + # Manual sync: allow agent to trigger full sync + config.rule :manual_sync do |r| + r.fields [:customer_context, :sla_context] + r.trigger :manual + r.direction :parent_to_children # All children + r.condition :always + r.timing :immediate + end +end +``` + +### Alternative: JSON Configuration + +For storage in Zammad's `Setting` table: + +```json +{ + "field_groups": { + "bridge_channel": [ + "preferences.channel_id", + "preferences.cdr_whatsapp", + "preferences.cdr_signal" + ], + "customer_context": [ + "organization_id", + "custom_account_id", + "custom_region" + ] + }, + "rules": [ + { + "name": "bridge_on_split", + "fields": ["@bridge_channel"], + "trigger": "split", + "direction": "parent_to_child", + "condition": "if_target_empty", + "enabled": true + }, + { + "name": "bridge_on_merge", + "fields": ["@bridge_channel"], + "trigger": "merge", + "direction": "source_to_target", + "condition": "if_target_empty", + "enabled": true + }, + { + "name": "customer_context_inherit", + "fields": ["@customer_context"], + "trigger": "split", + "direction": "parent_to_child", + "condition": "always", + "enabled": true + } + ] +} +``` + +--- + +## Architecture + +### Components + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ TicketFieldPropagation │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ +│ │ Configuration│ │ Engine │ │ FieldAccessor │ │ +│ │ │───▶│ │───▶│ │ │ +│ │ - field_groups │ - execute() │ │ - get(path) │ │ +│ │ - rules │ │ - apply_rule │ │ - set(path, val) │ │ +│ │ - load/save │ │ - find_related │ - deep_merge │ │ +│ └──────────────┘ └──────────────┘ └──────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ RelationshipFinder │ │ +│ │ │ │ +│ │ - find_parent(ticket) │ │ +│ │ - find_children(ticket) │ │ +│ │ - find_merge_target(ticket) │ │ +│ │ - find_merge_source(ticket) │ │ +│ └──────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ Triggers │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌────────────────┐ ┌────────────────┐ ┌─────────────────┐ │ +│ │ Ticket Concern │ │ Transaction │ │ Manual API │ │ +│ │ │ │ Observer │ │ Endpoint │ │ +│ │ after_create │ │ │ │ │ │ +│ │ after_update │ │ on merge event │ │ POST /tickets/ │ │ +│ │ after_save │ │ on split event │ │ :id/propagate │ │ +│ └────────────────┘ └────────────────┘ └─────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Class Design + +```ruby +# lib/ticket_field_propagation/configuration.rb +module TicketFieldPropagation + class Configuration + attr_accessor :field_groups, :rules + + def self.load + # Load from Setting table or YAML + end + + def field_group(name, fields) + @field_groups[name] = fields + end + + def rule(name, &block) + rule = Rule.new(name) + block.call(rule) + @rules << rule + end + + def expand_fields(field_refs) + # Expand @group_name references to actual field list + field_refs.flat_map do |ref| + if ref.start_with?('@') + @field_groups[ref[1..].to_sym] || [] + else + [ref] + end + end + end + end + + class Rule + attr_accessor :name, :fields, :trigger, :direction, :condition, :timing + + def initialize(name) + @name = name + @timing = :immediate + @condition = :always + end + + def applies_to?(event_type) + @trigger == event_type || (@trigger.is_a?(Array) && @trigger.include?(event_type)) + end + end +end +``` + +```ruby +# lib/ticket_field_propagation/engine.rb +module TicketFieldPropagation + class Engine + def initialize(source_ticket, event_type, target_ticket: nil) + @source = source_ticket + @event = event_type + @explicit_target = target_ticket + @config = Configuration.load + end + + def execute + applicable_rules.each do |rule| + if rule.timing == :deferred + PropagationJob.perform_later(@source.id, rule.name) + else + apply_rule(rule) + end + end + end + + private + + def applicable_rules + @config.rules.select { |r| r.applies_to?(@event) && r.enabled } + end + + def apply_rule(rule) + targets = find_targets(rule.direction) + fields = @config.expand_fields(rule.fields) + + targets.each do |target| + source = determine_source(rule.direction, target) + PropagationResult.log(@source, target, rule) + + fields.each do |field_path| + copy_field(source, target, field_path, rule.condition) + end + + target.save! if target.changed? + end + end + + def find_targets(direction) + case direction + when :parent_to_child, :parent_to_children + RelationshipFinder.find_children(@source) + when :child_to_parent + [RelationshipFinder.find_parent(@source)].compact + when :source_to_target + [@explicit_target || RelationshipFinder.find_merge_target(@source)].compact + else + [] + end + end + + def determine_source(direction, target) + case direction + when :parent_to_child, :parent_to_children, :source_to_target + @source + when :child_to_parent + target # We're copying FROM child TO parent, so target is source here + # Wait, this is confusing. Let me reconsider... + @source # The ticket that triggered the event is the source + end + end + + def copy_field(source, target, field_path, condition) + source_value = FieldAccessor.get(source, field_path) + return if source_value.nil? + + target_value = FieldAccessor.get(target, field_path) + + case condition + when :if_target_empty + return if target_value.present? + when :if_greater + return if target_value.present? && target_value >= source_value + when :always + # proceed + end + + FieldAccessor.set(target, field_path, source_value) + end + end +end +``` + +```ruby +# lib/ticket_field_propagation/field_accessor.rb +module TicketFieldPropagation + class FieldAccessor + class << self + def get(ticket, field_path) + parts = field_path.split('.') + + value = ticket + parts.each do |part| + value = access_part(value, part) + return nil if value.nil? + end + + # Deep dup hashes to prevent mutation + value.is_a?(Hash) ? value.deep_dup : value + end + + def set(ticket, field_path, value) + parts = field_path.split('.') + + if parts.length == 1 + # Direct attribute + set_attribute(ticket, parts[0], value) + else + # Nested in preferences or similar + set_nested(ticket, parts, value) + end + end + + private + + def access_part(object, part) + if object.is_a?(Hash) + object[part] || object[part.to_sym] + elsif object.respond_to?(part) + object.send(part) + elsif object.respond_to?(:[]) + object[part] + else + nil + end + end + + def set_attribute(ticket, attr_name, value) + if ticket.respond_to?("#{attr_name}=") + ticket.send("#{attr_name}=", value) + else + raise ArgumentError, "Unknown attribute: #{attr_name}" + end + end + + def set_nested(ticket, parts, value) + # e.g., ['preferences', 'cdr_whatsapp'] + root = parts[0] + + if root == 'preferences' + ticket.preferences ||= {} + set_hash_path(ticket.preferences, parts[1..], value) + else + raise ArgumentError, "Unsupported nested path root: #{root}" + end + end + + def set_hash_path(hash, remaining_parts, value) + if remaining_parts.length == 1 + key = remaining_parts[0] + if value.is_a?(Hash) && hash[key].is_a?(Hash) + # Deep merge for hash values + hash[key] = hash[key].deep_merge(value) + else + hash[key] = value + end + else + key = remaining_parts[0] + hash[key] ||= {} + set_hash_path(hash[key], remaining_parts[1..], value) + end + end + end + end +end +``` + +```ruby +# lib/ticket_field_propagation/relationship_finder.rb +module TicketFieldPropagation + class RelationshipFinder + class << self + def find_parent(ticket) + # In Zammad links: parent ticket has link_type 'child' pointing to it + # Wait, need to verify Zammad's link semantics... + # + # From merge: source ticket gets a 'parent' link pointing TO target + # Link.add(link_type: 'parent', source: target_id, target: source_id) + # + # So to find parent of a ticket, look for 'parent' links where + # this ticket is the target (link_object_target_value) + + links = Link.list( + link_object: 'Ticket', + link_object_value: ticket.id + ) + + parent_link = links.find { |l| l['link_type'] == 'parent' } + return nil unless parent_link + + Ticket.find_by(id: parent_link['link_object_value']) + end + + def find_children(ticket) + links = Link.list( + link_object: 'Ticket', + link_object_value: ticket.id + ) + + child_links = links.select { |l| l['link_type'] == 'child' } + child_ids = child_links.map { |l| l['link_object_value'] } + + Ticket.where(id: child_ids).to_a + end + + def find_merge_target(ticket) + # Merged ticket has 'parent' link to target + return nil unless ticket.state.state_type.name == 'merged' + find_parent(ticket) + end + + def find_merge_sources(ticket) + # Find tickets that were merged into this one + links = Link.list( + link_object: 'Ticket', + link_object_value: ticket.id + ) + + # Look for child links where the child is in merged state + child_links = links.select { |l| l['link_type'] == 'child' } + + child_links.filter_map do |link| + child = Ticket.find_by(id: link['link_object_value']) + child if child&.state&.state_type&.name == 'merged' + end + end + end + end +end +``` + +### Integration Points + +#### 1. Ticket Concern (for create/update triggers) + +```ruby +# app/models/ticket/field_propagation.rb +module Ticket::FieldPropagation + extend ActiveSupport::Concern + + included do + after_create :trigger_propagation_on_create + after_update :trigger_propagation_on_update + end + + private + + def trigger_propagation_on_create + # Check if this is a split (has parent link created simultaneously) + # This is tricky because link might be created after ticket... + # May need to hook into Link.add instead + end + + def trigger_propagation_on_update + return unless saved_change_to_attribute?(:state_id) + + if state.state_type.name == 'merged' + TicketFieldPropagation::Engine.new(self, :merge).execute + end + end +end +``` + +#### 2. Transaction Observer (for merge/split events) + +```ruby +# app/models/transaction/ticket_field_propagation.rb +class Transaction::TicketFieldPropagation + def self.execute(object, type, _changes, user_id, _options) + return unless object.is_a?(Ticket) + + case type + when 'update.merged_into' + # Source ticket was merged - propagate to target + target = TicketFieldPropagation::RelationshipFinder.find_merge_target(object) + TicketFieldPropagation::Engine.new(object, :merge, target_ticket: target).execute + + when 'update.received_merge' + # Target ticket received a merge - could trigger reverse propagation if needed + + when 'create' + # Check if this is from a split (check for immediate parent link) + parent = TicketFieldPropagation::RelationshipFinder.find_parent(object) + if parent.present? + TicketFieldPropagation::Engine.new(parent, :split, target_ticket: object).execute + end + end + end +end +``` + +#### 3. Manual API Endpoint + +```ruby +# app/controllers/ticket_field_propagation_controller.rb +class TicketFieldPropagationController < ApplicationController + before_action :authenticate_and_authorize + + # POST /api/v1/tickets/:id/propagate + def propagate + ticket = Ticket.find(params[:id]) + direction = params[:direction] || 'to_children' + fields = params[:fields] || 'all' + + case direction + when 'to_children' + engine = TicketFieldPropagation::Engine.new(ticket, :manual) + engine.execute_for_fields(fields, direction: :parent_to_children) + when 'from_parent' + parent = TicketFieldPropagation::RelationshipFinder.find_parent(ticket) + return render json: { error: 'No parent ticket' }, status: :not_found unless parent + + engine = TicketFieldPropagation::Engine.new(parent, :manual, target_ticket: ticket) + engine.execute_for_fields(fields, direction: :parent_to_child) + end + + render json: { success: true } + end + + # GET /api/v1/tickets/:id/propagation_preview + def preview + # Show what would be copied without doing it + end +end +``` + +--- + +## Handling Edge Cases + +### 1. Circular Reference Prevention + +```ruby +class Engine + MAX_DEPTH = 5 + + def execute(depth: 0) + return if depth >= MAX_DEPTH + + # Track processed tickets in this chain + Thread.current[:propagation_chain] ||= Set.new + return if Thread.current[:propagation_chain].include?(@source.id) + + Thread.current[:propagation_chain].add(@source.id) + + begin + # ... execute rules + ensure + Thread.current[:propagation_chain].delete(@source.id) + end + end +end +``` + +### 2. Conflicting Values on Merge + +When both source and target have values, the default is "don't overwrite" (`if_target_empty`). But we could support strategies: + +```ruby +config.rule :merge_preferences do |r| + r.fields ['preferences.cdr_whatsapp'] + r.trigger :merge + r.direction :source_to_target + r.condition :merge_hash # Deep merge instead of replace +end +``` + +Or with explicit conflict resolution: + +```ruby +r.on_conflict do |source_val, target_val, field| + case field + when /escalation/ + [source_val, target_val].max + when /preferences\.cdr_/ + target_val.presence || source_val # Keep target if present + else + source_val # Default: source wins + end +end +``` + +### 3. Multiple Bridge Channels + +If source has WhatsApp and target has Signal, we might want both: + +```ruby +# Current behavior with if_target_empty: +# - Source: {cdr_whatsapp: {...}} +# - Target: {cdr_signal: {...}} +# - Result: Target keeps cdr_signal, gains cdr_whatsapp (both present) + +# This works because we check per-field, not per-category +``` + +### 4. Signal Group Merge Validation + +Special case: don't allow merging tickets from different Signal groups: + +```ruby +config.rule :validate_signal_merge do |r| + r.trigger :merge + r.validator ->(source, target) { + source_group = source.preferences.dig('cdr_signal', 'chat_id') + target_group = target.preferences.dig('cdr_signal', 'chat_id') + + # OK if either doesn't have signal, or same group + return true if source_group.blank? || target_group.blank? + return true if source_group == target_group + + # Different groups - block the merge + raise Exceptions::UnprocessableEntity, + "Cannot merge tickets from different Signal groups" + } +end +``` + +--- + +## Audit Trail + +Track what was propagated for debugging and transparency: + +```ruby +# app/models/ticket_field_propagation_log.rb +class TicketFieldPropagationLog < ApplicationRecord + belongs_to :source_ticket, class_name: 'Ticket' + belongs_to :target_ticket, class_name: 'Ticket' + + # Columns: + # - source_ticket_id + # - target_ticket_id + # - rule_name + # - field_path + # - old_value (serialized) + # - new_value (serialized) + # - trigger_event + # - created_by_id + # - created_at +end +``` + +Or simpler: add to ticket history: + +```ruby +target_ticket.history_log( + 'field_propagated', + UserInfo.current_user_id, + value_from: source_ticket.id, + value_to: { field: field_path, value: new_value.to_s.truncate(100) } +) +``` + +--- + +## Configuration UI (Future) + +Admin interface at Settings → Ticket → Field Propagation: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Field Propagation Rules [+Add]│ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ [✓] Bridge Channel on Split [Edit] │ │ +│ │ Copy: preferences.cdr_whatsapp, preferences.cdr_signal │ │ +│ │ When: Ticket is split │ │ +│ │ Direction: Parent → Child │ │ +│ │ Condition: Only if child field is empty │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ [✓] Bridge Channel on Merge [Edit] │ │ +│ │ Copy: preferences.cdr_whatsapp, preferences.cdr_signal │ │ +│ │ When: Ticket is merged │ │ +│ │ Direction: Source → Target │ │ +│ │ Condition: Only if target field is empty │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +│ │ +│ ┌─────────────────────────────────────────────────────────────┐ │ +│ │ [ ] Customer Context Inheritance [Edit] │ │ +│ │ Copy: organization_id, custom_account_id, custom_region │ │ +│ │ When: Ticket is split │ │ +│ │ Direction: Parent → Child │ │ +│ │ Condition: Always │ │ +│ └─────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Default Configuration + +Out-of-the-box settings that solve the bridge preferences problem: + +```json +{ + "field_groups": { + "bridge_channel": [ + "preferences.channel_id", + "preferences.cdr_whatsapp", + "preferences.cdr_signal", + "preferences.cdr_voice" + ] + }, + "rules": [ + { + "name": "bridge_on_split", + "description": "Copy bridge channel info when splitting tickets", + "fields": ["@bridge_channel"], + "trigger": "split", + "direction": "parent_to_child", + "condition": "if_target_empty", + "enabled": true + }, + { + "name": "bridge_on_merge", + "description": "Copy bridge channel info when merging tickets", + "fields": ["@bridge_channel"], + "trigger": "merge", + "direction": "source_to_target", + "condition": "if_target_empty", + "enabled": true + } + ] +} +``` + +--- + +## Implementation Phases + +### Phase 1: Core Engine (Solves Bridge Problem) +- FieldAccessor with dot-notation support +- RelationshipFinder for parent/child/merge relationships +- Engine with basic rule processing +- Hardcoded rules for bridge channel propagation +- Integration with Ticket merge (via concern or observer) + +### Phase 2: Configuration System +- JSON configuration in Setting table +- Field groups support +- Multiple condition types (if_empty, always, if_greater) +- Deferred execution via jobs + +### Phase 3: Split Integration +- Hook into ticket split workflow +- Detect parent relationship after split +- Apply split rules + +### Phase 4: Manual Triggers +- API endpoint for manual propagation +- Preview endpoint +- Audit logging + +### Phase 5: Admin UI +- Configuration interface in Zammad admin +- Visual rule builder +- Field picker for custom object attributes + +### Phase 6: Advanced Features +- Bidirectional sync +- Conflict resolution strategies +- Cascading updates +- Validation rules (like Signal group merge prevention) + +--- + +## Files to Create + +``` +packages/zammad-addon-bridge/src/ +├── lib/ +│ └── ticket_field_propagation/ +│ ├── configuration.rb +│ ├── engine.rb +│ ├── field_accessor.rb +│ ├── relationship_finder.rb +│ └── propagation_job.rb +├── app/ +│ ├── models/ +│ │ └── ticket/ +│ │ └── field_propagation.rb # Concern +│ └── controllers/ +│ └── ticket_field_propagation_controller.rb +├── config/ +│ └── initializers/ +│ └── ticket_field_propagation.rb # Default config & include concern +└── db/ + └── seeds/ + └── field_propagation_settings.rb +``` + +--- + +## Relationship to Bridge Preferences Problem + +The bridge preferences problem from the previous investigation is solved by: + +1. **Default rule `bridge_on_merge`**: Copies `preferences.cdr_whatsapp` and `preferences.cdr_signal` from source to target when tickets are merged, if target doesn't already have them. + +2. **Default rule `bridge_on_split`**: Copies the same preferences from parent to child when tickets are split. + +3. **Extensibility**: Additional custom fields can be added to propagation rules without code changes. + +This makes the field propagation system a superset solution that handles the immediate bridge problem while providing a framework for future field synchronization needs. From f059e75acd68bb15c728149c4a8a3d03351edb47 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Fri, 19 Dec 2025 11:20:28 +0100 Subject: [PATCH 02/38] Add warning for unsent Signal groups messages. --- .../channels_cdr_signal_controller.rb | 30 +++++++++++++++++++ .../app/jobs/communicate_cdr_signal_job.rb | 27 +++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb index f09c458..409eac7 100644 --- a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb +++ b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb @@ -458,6 +458,36 @@ class ChannelsCdrSignalController < ApplicationController Rails.logger.info "Signal group member #{member_phone} joined group #{params[:group_id]} for ticket #{ticket.id}" + # Check if any articles had a group_not_joined notification and add resolution note + # Only add resolution note if we previously notified about the delivery issue + articles_with_pending_notification = Ticket::Article.where(ticket_id: ticket.id) + .where("preferences LIKE ?", "%group_not_joined_note_added: true%") + + if articles_with_pending_notification.exists? + # Check if we already added a resolution note for this ticket + resolution_note_exists = Ticket::Article.where(ticket_id: ticket.id) + .where("preferences LIKE ?", "%group_joined_resolution: true%") + .exists? + + unless resolution_note_exists + Ticket::Article.create( + ticket_id: ticket.id, + content_type: 'text/plain', + body: 'Recipient has now joined the Signal group. Pending messages will be delivered shortly.', + internal: true, + sender: Ticket::Article::Sender.find_by(name: 'System'), + type: Ticket::Article::Type.find_by(name: 'note'), + preferences: { + delivery_message: true, + group_joined_resolution: true, + }, + updated_by_id: 1, + created_by_id: 1, + ) + Rails.logger.info "Ticket ##{ticket.number}: Added resolution note about customer joining Signal group" + end + end + render json: { success: true, ticket_id: ticket.id, diff --git a/packages/zammad-addon-bridge/src/app/jobs/communicate_cdr_signal_job.rb b/packages/zammad-addon-bridge/src/app/jobs/communicate_cdr_signal_job.rb index 37e026a..786be4b 100644 --- a/packages/zammad-addon-bridge/src/app/jobs/communicate_cdr_signal_job.rb +++ b/packages/zammad-addon-bridge/src/app/jobs/communicate_cdr_signal_job.rb @@ -40,10 +40,37 @@ class CommunicateCdrSignalJob < ApplicationJob if is_group_chat && group_joined == false Rails.logger.info "Ticket ##{ticket.number}: User hasn't joined Signal group yet, skipping message delivery" + # Track group_not_joined retry attempts separately + article.preferences['group_not_joined_retry'] ||= 0 + article.preferences['group_not_joined_retry'] += 1 + # Mark article as pending delivery article.preferences['delivery_status'] = 'pending' article.preferences['delivery_status_message'] = 'Waiting for user to join Signal group' article.preferences['delivery_status_date'] = Time.zone.now + + # After 3 failed attempts, add a note to inform the agent (only once) + if article.preferences['group_not_joined_retry'] == 3 && !article.preferences['group_not_joined_note_added'] + Ticket::Article.create( + ticket_id: ticket.id, + content_type: 'text/plain', + body: 'Unable to send Signal message: Recipient has not yet joined the Signal group. ' \ + 'The message will be delivered automatically once they accept the group invitation.', + internal: true, + sender: Ticket::Article::Sender.find_by(name: 'System'), + type: Ticket::Article::Type.find_by(name: 'note'), + preferences: { + delivery_article_id_related: article.id, + delivery_message: true, + group_not_joined_notification: true, + }, + updated_by_id: 1, + created_by_id: 1, + ) + article.preferences['group_not_joined_note_added'] = true + Rails.logger.info "Ticket ##{ticket.number}: Added notification note about pending group join" + end + article.save! # Retry later when user might have joined From 0b2ea19ebc19057e686276e9b67c690b8674ccf0 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Fri, 19 Dec 2025 12:38:49 +0100 Subject: [PATCH 03/38] Add Signal group ticket split compatibility --- .../models/link/setup_split_signal_group.rb | 49 +++++++++++++++++++ .../src/config/initializers/cdr_signal.rb | 8 ++- 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 packages/zammad-addon-bridge/src/app/models/link/setup_split_signal_group.rb diff --git a/packages/zammad-addon-bridge/src/app/models/link/setup_split_signal_group.rb b/packages/zammad-addon-bridge/src/app/models/link/setup_split_signal_group.rb new file mode 100644 index 0000000..df07bba --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/models/link/setup_split_signal_group.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Link::SetupSplitSignalGroup + extend ActiveSupport::Concern + + included do + after_create :setup_signal_group_for_split_ticket + end + + private + + def setup_signal_group_for_split_ticket + # Only if auto-groups enabled + return unless ENV['BRIDGE_SIGNAL_AUTO_GROUPS'].to_s.downcase == 'true' + + # Only child links (splits create child->parent links) + return unless link_type_id == Link::Type.find_by(name: 'child')&.id + + # Only Ticket-to-Ticket links + ticket_object_id = Link::Object.find_by(name: 'Ticket')&.id + return unless link_object_source_id == ticket_object_id + return unless link_object_target_id == ticket_object_id + + child_ticket = Ticket.find_by(id: link_object_source_value) + parent_ticket = Ticket.find_by(id: link_object_target_value) + return unless child_ticket && parent_ticket + + # Only if parent has Signal group (chat_id starts with "group.") + parent_signal_prefs = parent_ticket.preferences&.dig('cdr_signal') + return unless parent_signal_prefs.present? + return unless parent_signal_prefs['chat_id']&.start_with?('group.') + + original_recipient = parent_signal_prefs['original_recipient'] + return unless original_recipient.present? + + # Set up child for lazy group creation: + # chat_id = phone number triggers new group on first message + child_ticket.preferences ||= {} + child_ticket.preferences['channel_id'] = parent_ticket.preferences['channel_id'] + child_ticket.preferences['cdr_signal'] = { + 'bot_token' => parent_signal_prefs['bot_token'], + 'chat_id' => original_recipient, # Phone number, NOT group ID + 'original_recipient' => original_recipient + } + child_ticket.save! + + Rails.logger.info "Signal split: Ticket ##{child_ticket.number} set up for new group (recipient: #{original_recipient})" + end +end diff --git a/packages/zammad-addon-bridge/src/config/initializers/cdr_signal.rb b/packages/zammad-addon-bridge/src/config/initializers/cdr_signal.rb index f00feca..c56d0ee 100644 --- a/packages/zammad-addon-bridge/src/config/initializers/cdr_signal.rb +++ b/packages/zammad-addon-bridge/src/config/initializers/cdr_signal.rb @@ -1,10 +1,15 @@ # frozen_string_literal: true -Rails.application.config.after_initialize do +Rails.application.config.after_initialize do class Ticket::Article include Ticket::Article::EnqueueCommunicateCdrSignalJob end + # Handle Signal group setup for split tickets + class Link + include Link::SetupSplitSignalGroup + end + icon = File.read('public/assets/images/icons/cdr_signal.svg') doc = File.open('public/assets/images/icons.svg') { |f| Nokogiri::XML(f) } if !doc.at_css('#icon-cdr-signal') @@ -15,4 +20,3 @@ Rails.application.config.after_initialize do end File.write('public/assets/images/icons.svg', doc.to_xml) end - \ No newline at end of file From 69394c813d5843de45279a5f3d7926170986b1ed Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Fri, 19 Dec 2025 12:52:47 +0100 Subject: [PATCH 04/38] Prevent overwriting a Signal group in Zammad if one already exists --- .../channels_cdr_signal_controller.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb index 409eac7..6446ba2 100644 --- a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb +++ b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb @@ -374,6 +374,24 @@ class ChannelsCdrSignalController < ApplicationController return end + # Idempotency check: if chat_id is already a group ID, don't overwrite it + # This prevents race conditions where multiple group_created webhooks arrive + # (e.g., due to retries after API timeouts during group creation) + existing_chat_id = ticket.preferences&.dig(:cdr_signal, :chat_id) || + ticket.preferences&.dig('cdr_signal', 'chat_id') + if existing_chat_id&.start_with?('group.') + Rails.logger.info "Signal group update: Ticket #{ticket.id} already has group #{existing_chat_id}, ignoring new group #{params[:group_id]}" + render json: { + success: true, + skipped: true, + reason: 'Ticket already has a group assigned', + existing_group_id: existing_chat_id, + ticket_id: ticket.id, + ticket_number: ticket.number + }, status: :ok + return + end + # Update ticket preferences with the group information ticket.preferences ||= {} ticket.preferences[:cdr_signal] ||= {} From a882c9ecffb90e281abd721cf6b102256b55791f Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Fri, 19 Dec 2025 15:27:27 +0100 Subject: [PATCH 05/38] Split ticket and group name fixes --- .../tasks/signal/send-signal-message.ts | 29 +++++++++++++++++++ docker/scripts/docker.js | 6 ---- docker/zammad/Dockerfile | 2 +- .../channels_cdr_signal_controller.rb | 5 ++++ .../models/link/setup_split_signal_group.rb | 2 ++ 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/apps/bridge-worker/tasks/signal/send-signal-message.ts b/apps/bridge-worker/tasks/signal/send-signal-message.ts index 3235be2..144dfe3 100644 --- a/apps/bridge-worker/tasks/signal/send-signal-message.ts +++ b/apps/bridge-worker/tasks/signal/send-signal-message.ts @@ -282,6 +282,35 @@ const sendSignalMessageTask = async ({ }, "Message sent successfully", ); + + // Update group name to use consistent template with ticket number + // This ensures groups created by receive-signal-message get renamed + // to match the template (e.g., "Support Request: 94085") + if (finalTo.startsWith("group.") && conversationId) { + try { + const expectedGroupName = buildSignalGroupName(conversationId); + await groupsClient.v1GroupsNumberGroupidPut({ + number: bot.phoneNumber, + groupid: finalTo, + data: { + name: expectedGroupName, + }, + }); + logger.debug( + { groupId: finalTo, newName: expectedGroupName }, + "Updated group name", + ); + } catch (renameError) { + // Non-fatal - group name update is best-effort + logger.warn( + { + error: renameError instanceof Error ? renameError.message : renameError, + groupId: finalTo, + }, + "Could not update group name", + ); + } + } } catch (error: any) { // Try to get the actual error message from the response if (error.response) { diff --git a/docker/scripts/docker.js b/docker/scripts/docker.js index 3d6e278..deb78ab 100644 --- a/docker/scripts/docker.js +++ b/docker/scripts/docker.js @@ -20,12 +20,6 @@ const envFile = path.resolve(process.cwd(), '.env'); const finalFiles = files[app] .map((file) => ['-f', `docker/compose/${file}.yml`]).flat(); -// Add bridge-dev.yml for dev commands that include zammad -const devAppsWithZammad = ['linkDev', 'bridgeDev', 'all']; -if (devAppsWithZammad.includes(app) && files[app].includes('zammad')) { - finalFiles.push('-f', 'docker-compose.bridge-dev.yml'); -} - const finalCommand = command === "up" ? ["up", "-d", "--remove-orphans"] : [command]; const dockerCompose = spawn('docker', ['compose', '--env-file', envFile, ...finalFiles, ...finalCommand]); diff --git a/docker/zammad/Dockerfile b/docker/zammad/Dockerfile index 018304d..dc7bf5a 100644 --- a/docker/zammad/Dockerfile +++ b/docker/zammad/Dockerfile @@ -66,7 +66,7 @@ RUN if [ "$EMBEDDED" = "true" ] ; then \ sed -i '$ d' /opt/zammad/contrib/nginx/zammad.conf && \ echo "" >> /opt/zammad/contrib/nginx/zammad.conf && \ echo " location /link {" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo " proxy_pass ${LINK_HOST};" >> /opt/zammad/contrib/nginx/zammad.conf && \ + echo " set \$link_url ${LINK_HOST}; proxy_pass \$link_url;" >> /opt/zammad/contrib/nginx/zammad.conf && \ echo " proxy_set_header Host \$host;" >> /opt/zammad/contrib/nginx/zammad.conf && \ echo " proxy_set_header X-Real-IP \$remote_addr;" >> /opt/zammad/contrib/nginx/zammad.conf && \ echo " proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;" >> /opt/zammad/contrib/nginx/zammad.conf && \ diff --git a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb index 6446ba2..4e85c9c 100644 --- a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb +++ b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb @@ -264,6 +264,11 @@ class ChannelsCdrSignalController < ApplicationController chat_id: chat_id } + # Store original recipient phone for group tickets to enable ticket splitting + if is_group_message + cdr_signal_prefs[:original_recipient] = sender_phone_number + end + Rails.logger.info "=== CREATING NEW TICKET ===" Rails.logger.info "Preferences to be stored:" Rails.logger.info " - channel_id: #{channel.id}" diff --git a/packages/zammad-addon-bridge/src/app/models/link/setup_split_signal_group.rb b/packages/zammad-addon-bridge/src/app/models/link/setup_split_signal_group.rb index df07bba..b7db245 100644 --- a/packages/zammad-addon-bridge/src/app/models/link/setup_split_signal_group.rb +++ b/packages/zammad-addon-bridge/src/app/models/link/setup_split_signal_group.rb @@ -42,6 +42,8 @@ module Link::SetupSplitSignalGroup 'chat_id' => original_recipient, # Phone number, NOT group ID 'original_recipient' => original_recipient } + # Set article type so Zammad shows Signal reply option + child_ticket.create_article_type_id = Ticket::Article::Type.find_by(name: 'cdr_signal')&.id child_ticket.save! Rails.logger.info "Signal split: Ticket ##{child_ticket.number} set up for new group (recipient: #{original_recipient})" From 3b91c98d5e8d25ad14dc5820ab595c7d8a1524b5 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Mon, 12 Jan 2026 10:01:44 +0100 Subject: [PATCH 06/38] Bump version to 3.5.0-beta.1 --- .gitlab-ci.yml | 10 ++++++++-- apps/bridge-frontend/package.json | 2 +- apps/bridge-migrations/package.json | 2 +- apps/bridge-whatsapp/package.json | 2 +- apps/bridge-worker/package.json | 2 +- apps/link/package.json | 2 +- package.json | 2 +- packages/bridge-common/package.json | 2 +- packages/bridge-ui/package.json | 2 +- packages/eslint-config/package.json | 2 +- packages/jest-config/package.json | 2 +- packages/logger/package.json | 2 +- packages/signal-api/package.json | 2 +- packages/typescript-config/package.json | 2 +- packages/ui/package.json | 2 +- packages/zammad-addon-bridge/package.json | 2 +- packages/zammad-addon-common/package.json | 2 +- packages/zammad-addon-hardening/package.json | 2 +- 18 files changed, 25 insertions(+), 19 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f848a7f..8fcd82b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,11 +20,13 @@ build-all: - turbo build .docker-build: - image: registry.gitlab.com/digiresilience/link/link-stack/buildx:${CI_COMMIT_REF_NAME} + image: registry.gitlab.com/digiresilience/link/link-stack/buildx:main services: - docker:dind stage: docker-build variables: + DOCKER_HOST: tcp://docker:2375 + DOCKER_TLS_CERTDIR: "" DOCKER_TAG: ${CI_COMMIT_SHORT_SHA} BUILD_CONTEXT: . only: @@ -37,11 +39,13 @@ build-all: - docker push ${DOCKER_NS}:${DOCKER_TAG} .docker-release: - image: registry.gitlab.com/digiresilience/link/link-stack/buildx:${CI_COMMIT_REF_NAME} + image: registry.gitlab.com/digiresilience/link/link-stack/buildx:main services: - docker:dind stage: docker-release variables: + DOCKER_HOST: tcp://docker:2375 + DOCKER_TLS_CERTDIR: "" DOCKER_TAG: ${CI_COMMIT_SHORT_SHA} DOCKER_TAG_NEW: ${CI_COMMIT_REF_NAME} only: @@ -195,6 +199,7 @@ zammad-docker-build: PNPM_HOME: "/pnpm" before_script: - export PATH="$PNPM_HOME:$PATH" + - corepack enable && corepack prepare pnpm@9.15.4 --activate script: - pnpm add -g turbo - pnpm install --frozen-lockfile @@ -217,6 +222,7 @@ zammad-standalone-docker-build: PNPM_HOME: "/pnpm" before_script: - export PATH="$PNPM_HOME:$PATH" + - corepack enable && corepack prepare pnpm@9.15.4 --activate script: - pnpm add -g turbo - pnpm install --frozen-lockfile diff --git a/apps/bridge-frontend/package.json b/apps/bridge-frontend/package.json index 028641a..27c4a82 100644 --- a/apps/bridge-frontend/package.json +++ b/apps/bridge-frontend/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-frontend", - "version": "3.3.5", + "version": "3.5.0-beta.1", "type": "module", "scripts": { "dev": "next dev", diff --git a/apps/bridge-migrations/package.json b/apps/bridge-migrations/package.json index b6740ce..3c23b1c 100644 --- a/apps/bridge-migrations/package.json +++ b/apps/bridge-migrations/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-migrations", - "version": "3.3.5", + "version": "3.5.0-beta.1", "type": "module", "scripts": { "migrate:up:all": "tsx migrate.ts up:all", diff --git a/apps/bridge-whatsapp/package.json b/apps/bridge-whatsapp/package.json index cef6520..97ea951 100644 --- a/apps/bridge-whatsapp/package.json +++ b/apps/bridge-whatsapp/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-whatsapp", - "version": "3.3.5", + "version": "3.5.0-beta.1", "main": "build/main/index.js", "author": "Darren Clarke ", "license": "AGPL-3.0-or-later", diff --git a/apps/bridge-worker/package.json b/apps/bridge-worker/package.json index 670d742..7d7e8ff 100644 --- a/apps/bridge-worker/package.json +++ b/apps/bridge-worker/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-worker", - "version": "3.3.5", + "version": "3.5.0-beta.1", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/link/package.json b/apps/link/package.json index 1f15196..45e61a3 100644 --- a/apps/link/package.json +++ b/apps/link/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/link", - "version": "3.3.5", + "version": "3.5.0-beta.1", "type": "module", "scripts": { "dev": "next dev -H 0.0.0.0", diff --git a/package.json b/package.json index 0a59707..e5d4c1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "Link from the Center for Digital Resilience", "scripts": { "dev": "dotenv -- turbo dev", diff --git a/packages/bridge-common/package.json b/packages/bridge-common/package.json index 91b9696..eecd5ee 100644 --- a/packages/bridge-common/package.json +++ b/packages/bridge-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-common", - "version": "3.3.5", + "version": "3.5.0-beta.1", "main": "build/main/index.js", "type": "module", "author": "Darren Clarke ", diff --git a/packages/bridge-ui/package.json b/packages/bridge-ui/package.json index 2e4d6fa..a2ca393 100644 --- a/packages/bridge-ui/package.json +++ b/packages/bridge-ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-ui", - "version": "3.3.5", + "version": "3.5.0-beta.1", "scripts": { "build": "tsc -p tsconfig.json" }, diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index c579d56..331d500 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/eslint-config", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "amigo's eslint config", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index 591a33a..1d845b3 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/jest-config", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/logger/package.json b/packages/logger/package.json index cda0e71..9948916 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/logger", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "Shared logging utility for Link Stack monorepo", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/packages/signal-api/package.json b/packages/signal-api/package.json index 0905a16..bf17ff6 100644 --- a/packages/signal-api/package.json +++ b/packages/signal-api/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/signal-api", - "version": "3.3.5", + "version": "3.5.0-beta.1", "type": "module", "main": "build/index.js", "exports": { diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 98021b8..a5f03be 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/typescript-config", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "Shared TypeScript config", "license": "AGPL-3.0-or-later", "author": "Abel Luck ", diff --git a/packages/ui/package.json b/packages/ui/package.json index a12655e..bb5f0a1 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/ui", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "", "scripts": { "build": "tsc -p tsconfig.json" diff --git a/packages/zammad-addon-bridge/package.json b/packages/zammad-addon-bridge/package.json index a7ef115..f0f1e93 100644 --- a/packages/zammad-addon-bridge/package.json +++ b/packages/zammad-addon-bridge/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-bridge", "displayName": "Bridge", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "An addon that adds CDR Bridge channels to Zammad.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", diff --git a/packages/zammad-addon-common/package.json b/packages/zammad-addon-common/package.json index 2b3c510..2b252e4 100644 --- a/packages/zammad-addon-common/package.json +++ b/packages/zammad-addon-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/zammad-addon-common", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "", "bin": { "zpm-build": "./dist/build.js", diff --git a/packages/zammad-addon-hardening/package.json b/packages/zammad-addon-hardening/package.json index 725472b..dc1373e 100644 --- a/packages/zammad-addon-hardening/package.json +++ b/packages/zammad-addon-hardening/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-hardening", "displayName": "Hardening", - "version": "3.3.5", + "version": "3.5.0-beta.1", "description": "A Zammad addon that hardens a Zammad instance according to CDR's needs.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", From e952973f7f396b83ca8a60ee27abbd1c411b985e Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Tue, 2 Dec 2025 16:55:07 +0100 Subject: [PATCH 07/38] Update Baileys to 7RC --- .nvmrc | 2 +- apps/bridge-whatsapp/package.json | 9 +- apps/bridge-whatsapp/src/index.ts | 6 +- apps/bridge-whatsapp/src/routes.ts | 12 +- apps/bridge-whatsapp/src/service.ts | 14 +- apps/bridge-whatsapp/src/types.ts | 2 +- apps/bridge-whatsapp/tsconfig.json | 11 +- package.json | 2 +- pnpm-lock.yaml | 1826 ++++++++++++++------------- 9 files changed, 984 insertions(+), 900 deletions(-) diff --git a/.nvmrc b/.nvmrc index 32cfab6..54c6511 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v22.18.0 +v24 diff --git a/apps/bridge-whatsapp/package.json b/apps/bridge-whatsapp/package.json index cef6520..5d4ad9e 100644 --- a/apps/bridge-whatsapp/package.json +++ b/apps/bridge-whatsapp/package.json @@ -1,17 +1,17 @@ { "name": "@link-stack/bridge-whatsapp", "version": "3.3.5", + "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", "license": "AGPL-3.0-or-later", "dependencies": { - "@adiwajshing/keyed-db": "0.2.4", "@hapi/hapi": "^21.4.3", "@hapipal/schmervice": "^3.0.0", "@hapipal/toys": "^4.0.0", "@link-stack/bridge-common": "workspace:*", "@link-stack/logger": "workspace:*", - "@whiskeysockets/baileys": "6.7.21", + "@whiskeysockets/baileys": "7.0.0-rc.9", "hapi-pino": "^13.0.0", "link-preview-js": "^3.1.0" }, @@ -19,15 +19,12 @@ "@link-stack/eslint-config": "workspace:*", "@link-stack/jest-config": "workspace:*", "@link-stack/typescript-config": "workspace:*", - "@types/long": "^5", "@types/node": "*", - "dotenv-cli": "^10.0.0", - "tsx": "^4.20.6", "typescript": "^5.9.3" }, "scripts": { "build": "tsc -p tsconfig.json", - "dev": "dotenv -- tsx src/index.ts", + "dev": "node --env-file=.env --experimental-transform-types src/index.ts", "start": "node build/main/index.js" } } diff --git a/apps/bridge-whatsapp/src/index.ts b/apps/bridge-whatsapp/src/index.ts index 5be8763..bd255ff 100644 --- a/apps/bridge-whatsapp/src/index.ts +++ b/apps/bridge-whatsapp/src/index.ts @@ -1,17 +1,17 @@ import * as Hapi from "@hapi/hapi"; import hapiPino from "hapi-pino"; import Schmervice from "@hapipal/schmervice"; -import WhatsappService from "./service.js"; +import WhatsappService from "./service.ts"; import { RegisterBotRoute, UnverifyBotRoute, GetBotRoute, SendMessageRoute, ReceiveMessageRoute, -} from "./routes.js"; +} from "./routes.ts"; import { createLogger } from "@link-stack/logger"; -const logger = createLogger('bridge-whatsapp-index'); +const logger = createLogger("bridge-whatsapp-index"); const server = Hapi.server({ port: 5000 }); diff --git a/apps/bridge-whatsapp/src/routes.ts b/apps/bridge-whatsapp/src/routes.ts index 1d9caf6..7315020 100644 --- a/apps/bridge-whatsapp/src/routes.ts +++ b/apps/bridge-whatsapp/src/routes.ts @@ -1,6 +1,6 @@ import * as Hapi from "@hapi/hapi"; import Toys from "@hapipal/toys"; -import WhatsappService from "./service"; +import WhatsappService from "./service.ts"; const withDefaults = Toys.withRouteDefaults({ options: { @@ -27,15 +27,9 @@ export const SendMessageRoute = withDefaults({ description: "Send a message", async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) { const { id } = request.params; - const { phoneNumber, message, attachments } = - request.payload as MessageRequest; + const { phoneNumber, message, attachments } = request.payload as MessageRequest; const whatsappService = getService(request); - await whatsappService.send( - id, - phoneNumber, - message as string, - attachments, - ); + await whatsappService.send(id, phoneNumber, message as string, attachments); request.logger.info( { id, diff --git a/apps/bridge-whatsapp/src/service.ts b/apps/bridge-whatsapp/src/service.ts index 69a1895..32701f7 100644 --- a/apps/bridge-whatsapp/src/service.ts +++ b/apps/bridge-whatsapp/src/service.ts @@ -4,12 +4,13 @@ import makeWASocket, { DisconnectReason, proto, downloadContentFromMessage, - MediaType, fetchLatestBaileysVersion, isJidBroadcast, isJidStatusBroadcast, useMultiFileAuthState, } from "@whiskeysockets/baileys"; + +type MediaType = "audio" | "document" | "image" | "video" | "sticker"; import fs from "fs"; import { createLogger } from "@link-stack/logger"; import { @@ -175,11 +176,12 @@ export default class WhatsappService extends Service { } private async queueMessage(botID: string, webMessageInfo: proto.IWebMessageInfo) { - const { - key: { id, fromMe, remoteJid }, - message, - messageTimestamp, - } = webMessageInfo; + const { key, message, messageTimestamp } = webMessageInfo; + if (!key) { + logger.warn("Message missing key, skipping"); + return; + } + const { id, fromMe, remoteJid } = key; logger.info("Message type debug"); for (const key in message) { logger.info( diff --git a/apps/bridge-whatsapp/src/types.ts b/apps/bridge-whatsapp/src/types.ts index 231a804..dc6d4fb 100644 --- a/apps/bridge-whatsapp/src/types.ts +++ b/apps/bridge-whatsapp/src/types.ts @@ -1,4 +1,4 @@ -import type WhatsappService from "./service.js"; +import type WhatsappService from "./service.ts"; declare module "@hapipal/schmervice" { interface SchmerviceDecorator { diff --git a/apps/bridge-whatsapp/tsconfig.json b/apps/bridge-whatsapp/tsconfig.json index 4b714ce..dce4015 100644 --- a/apps/bridge-whatsapp/tsconfig.json +++ b/apps/bridge-whatsapp/tsconfig.json @@ -1,16 +1,17 @@ { "extends": "@link-stack/typescript-config/tsconfig.node.json", "compilerOptions": { - "module": "commonjs", - "target": "es2018", + "module": "NodeNext", + "target": "es2022", "esModuleInterop": true, - "moduleResolution": "node", + "moduleResolution": "NodeNext", "outDir": "build/main", "rootDir": "src", "skipLibCheck": true, "types": ["node"], - "lib": ["es2020", "DOM"], - "composite": true + "lib": ["es2022", "DOM"], + "composite": true, + "rewriteRelativeImportExtensions": true }, "include": ["src/**/*.ts", "src/**/.*.ts"], "exclude": ["node_modules/**"] diff --git a/package.json b/package.json index 0a59707..df74908 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "react": "19.2.0", "react-dom": "19.2.0", "ts-node": "^10.9.2", - "turbo": "^2.5.8", + "turbo": "^2.6.0", "typescript": "latest" }, "pnpm": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 647ef91..c415592 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,7 +26,7 @@ importers: version: 11.0.0 eslint: specifier: ^9 - version: 9.39.2 + version: 9.39.1 react: specifier: 19.2.0 version: 19.2.0 @@ -35,10 +35,10 @@ importers: version: 19.2.0(react@19.2.0) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@24.10.4)(typescript@5.9.3) + version: 10.9.2(@types/node@24.10.0)(typescript@5.9.3) turbo: - specifier: ^2.5.8 - version: 2.6.3 + specifier: ^2.6.0 + version: 2.6.0 typescript: specifier: latest version: 5.9.3 @@ -65,16 +65,16 @@ importers: version: 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/material-nextjs': specifier: ^6 - version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) + version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) '@mui/x-license': specifier: ^7 version: 7.29.1(@types/react@19.2.2)(react@19.2.0) next: - specifier: 15.5.9 - version: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 15.5.4 + version: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) next-auth: specifier: ^4.24.11 - version: 4.24.13(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 4.24.13(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: 19.2.0 version: 19.2.0 @@ -86,7 +86,7 @@ importers: version: 0.34.5 tsx: specifier: ^4.20.6 - version: 4.21.0 + version: 4.20.6 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -96,10 +96,10 @@ importers: version: link:../../packages/typescript-config '@types/node': specifier: ^24 - version: 24.10.4 + version: 24.10.0 '@types/pg': specifier: ^8.15.5 - version: 8.16.0 + version: 8.15.6 '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -126,7 +126,7 @@ importers: version: 8.16.3 tsx: specifier: ^4.20.6 - version: 4.21.0 + version: 4.20.6 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -136,19 +136,16 @@ importers: version: link:../../packages/typescript-config '@types/node': specifier: ^24 - version: 24.10.4 + version: 24.10.0 '@types/pg': specifier: ^8.15.5 - version: 8.16.0 + version: 8.15.6 typescript: specifier: ^5 version: 5.9.3 apps/bridge-whatsapp: dependencies: - '@adiwajshing/keyed-db': - specifier: 0.2.4 - version: 0.2.4 '@hapi/hapi': specifier: ^21.4.3 version: 21.4.4 @@ -165,14 +162,11 @@ importers: specifier: workspace:* version: link:../../packages/logger '@whiskeysockets/baileys': - specifier: 6.7.21 - version: 6.7.21(link-preview-js@3.2.0)(sharp@0.34.5) + specifier: 7.0.0-rc.9 + version: 7.0.0-rc.9(link-preview-js@3.1.0)(sharp@0.34.5) hapi-pino: specifier: ^13.0.0 version: 13.0.0 - link-preview-js: - specifier: ^3.1.0 - version: 3.2.0 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -183,18 +177,9 @@ importers: '@link-stack/typescript-config': specifier: workspace:* version: link:../../packages/typescript-config - '@types/long': - specifier: ^5 - version: 5.0.0 '@types/node': specifier: '*' - version: 24.10.4 - dotenv-cli: - specifier: ^10.0.0 - version: 10.0.0 - tsx: - specifier: ^4.20.6 - version: 4.21.0 + version: 24.10.0 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -224,7 +209,7 @@ importers: version: 2.32.0 twilio: specifier: ^5.10.2 - version: 5.11.1 + version: 5.10.4 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -282,10 +267,10 @@ importers: version: 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/material-nextjs': specifier: ^6 - version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) + version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) '@mui/x-data-grid-pro': specifier: ^7 - version: 7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-date-pickers': specifier: ^7 version: 7.29.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(date-fns@4.1.0)(dayjs@1.11.19)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -300,7 +285,7 @@ importers: version: 4.1.0 graphql-request: specifier: ^7.2.0 - version: 7.4.0(graphql@16.12.0) + version: 7.3.1(graphql@16.12.0) ioredis: specifier: ^5.8.1 version: 5.8.2 @@ -308,11 +293,11 @@ importers: specifier: ^6.0.0 version: 6.0.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/icons-material@6.5.0(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) next: - specifier: 15.5.9 - version: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 15.5.4 + version: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) next-auth: specifier: ^4.24.11 - version: 4.24.13(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 4.24.13(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: 19.2.0 version: 19.2.0 @@ -337,7 +322,7 @@ importers: version: link:../../packages/eslint-config '@types/node': specifier: ^24.7.0 - version: 24.10.4 + version: 24.10.0 '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -365,7 +350,7 @@ importers: version: link:../typescript-config '@types/pg': specifier: ^8.15.5 - version: 8.16.0 + version: 8.15.6 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -386,13 +371,13 @@ importers: version: 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-data-grid-pro': specifier: ^7 - version: 7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) kysely: specifier: 0.27.5 version: 0.27.5 next: - specifier: 15.5.9 - version: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 15.5.4 + version: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: 19.2.0 version: 19.2.0 @@ -405,7 +390,7 @@ importers: devDependencies: '@types/node': specifier: ^24.7.0 - version: 24.10.4 + version: 24.10.0 '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -420,44 +405,44 @@ importers: dependencies: '@babel/eslint-parser': specifier: 7.28.4 - version: 7.28.4(@babel/core@7.28.5)(eslint@9.39.2) + version: 7.28.4(@babel/core@7.28.5)(eslint@9.39.1) '@rushstack/eslint-patch': specifier: ^1.13.0 - version: 1.15.0 + version: 1.14.1 '@typescript-eslint/eslint-plugin': specifier: ^8.46.0 - version: 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + version: 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) '@typescript-eslint/parser': specifier: ^8.46.0 - version: 8.50.0(eslint@9.39.2)(typescript@5.9.3) + version: 8.46.3(eslint@9.39.1)(typescript@5.9.3) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.2) + version: 10.1.8(eslint@9.39.1) eslint-config-xo-space: specifier: ^0.35.0 - version: 0.35.0(eslint@9.39.2) + version: 0.35.0(eslint@9.39.1) eslint-plugin-eslint-comments: specifier: ^3.2.0 - version: 3.2.0(eslint@9.39.2) + version: 3.2.0(eslint@9.39.1) eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) + version: 2.32.0(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1) eslint-plugin-jest: specifier: ^29.0.1 - version: 29.5.0(@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(jest@30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.0.1(@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)))(typescript@5.9.3) eslint-plugin-promise: specifier: ^7.2.1 - version: 7.2.1(eslint@9.39.2) + version: 7.2.1(eslint@9.39.1) eslint-plugin-unicorn: specifier: 61.0.2 - version: 61.0.2(eslint@9.39.2) + version: 61.0.2(eslint@9.39.1) devDependencies: eslint: specifier: ^9 - version: 9.39.2 + version: 9.39.1 jest: specifier: ^30.2.0 - version: 30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)) + version: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -469,7 +454,7 @@ importers: version: 30.0.0 jest: specifier: ^30.2.0 - version: 30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)) + version: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) jest-junit: specifier: ^16.0.0 version: 16.0.0 @@ -481,7 +466,7 @@ importers: version: 10.1.0 pino-pretty: specifier: ^13.1.1 - version: 13.1.3 + version: 13.1.2 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -491,13 +476,13 @@ importers: version: link:../typescript-config '@types/node': specifier: ^24.7.0 - version: 24.10.4 + version: 24.10.0 eslint: specifier: ^9.37.0 - version: 9.39.2 + version: 9.39.1 tsup: specifier: ^8.5.0 - version: 8.5.1(postcss@8.4.31)(tsx@4.21.0)(typescript@5.9.3) + version: 8.5.0(postcss@8.4.31)(tsx@4.20.6)(typescript@5.9.3) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -512,10 +497,10 @@ importers: version: link:../typescript-config '@openapitools/openapi-generator-cli': specifier: ^2.24.0 - version: 2.25.2(@types/node@24.10.4) + version: 2.25.0(@types/node@24.10.0) '@types/node': specifier: ^24 - version: 24.10.4 + version: 24.10.0 typescript: specifier: ^5 version: 5.9.3 @@ -532,13 +517,13 @@ importers: version: 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-data-grid-pro': specifier: ^7 - version: 7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-license': specifier: ^7 version: 7.29.1(@types/react@19.2.2)(react@19.2.0) next: - specifier: 15.5.9 - version: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 15.5.4 + version: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: 19.2.0 version: 19.2.0 @@ -548,7 +533,7 @@ importers: devDependencies: '@types/node': specifier: ^24.7.0 - version: 24.10.4 + version: 24.10.0 '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -572,11 +557,11 @@ importers: version: link:../logger glob: specifier: ^11.0.3 - version: 11.1.0 + version: 11.0.3 devDependencies: '@types/node': specifier: ^24.7.0 - version: 24.10.4 + version: 24.10.0 typescript: specifier: ^5 version: 5.9.3 @@ -589,9 +574,6 @@ importers: packages: - '@adiwajshing/keyed-db@0.2.4': - resolution: {integrity: sha512-yprSnAtj80/VKuDqRcFFLDYltoNV8tChNwFfIgcf6PGD4sjzWIBgs08pRuTqGH5mk5wgL6PBRSsMCZqtZwzFEw==} - '@auth/core@0.41.1': resolution: {integrity: sha512-t9cJ2zNYAdWMacGRMT6+r4xr1uybIdmYa49calBPeTqwgAFPV/88ac9TEvCR85pvATiSPt8VaNf+Gt24JIT/uw==} peerDependencies: @@ -793,15 +775,18 @@ packages: '@borewit/text-codec@0.2.0': resolution: {integrity: sha512-X999CKBxGwX8wW+4gFibsbiNdwqmdQEXmUejIWaIqdrHBgS5ARIOOeyiQbHjP9G58xVEPcuvP6VwwH3A0OFTOA==} - '@cacheable/memory@2.0.6': - resolution: {integrity: sha512-7e8SScMocHxcAb8YhtkbMhGG+EKLRIficb1F5sjvhSYsWTZGxvg4KIDp8kgxnV2PUJ3ddPe6J9QESjKvBWRDkg==} + '@cacheable/memoize@2.0.3': + resolution: {integrity: sha512-hl9wfQgpiydhQEIv7fkjEzTGE+tcosCXLKFDO707wYJ/78FVOlowb36djex5GdbSyeHnG62pomYLMuV/OT8Pbw==} - '@cacheable/node-cache@1.7.6': - resolution: {integrity: sha512-6Omk2SgNnjtxB5f/E6bTIWIt5xhdpx39fGNRQgU9lojvRxU68v+qY+SXXLsp3ZGukqoPjsK21wZ6XABFr/Ge3A==} + '@cacheable/memory@2.0.4': + resolution: {integrity: sha512-cCmJKCKlT1t7hNBI1+gFCwmKFd9I4pS3zqBeNGXTSODnpa0EeDmORHY8oEMTuozfdg3cgsVh8ojLaPYb6eC7Cg==} + + '@cacheable/node-cache@1.7.4': + resolution: {integrity: sha512-XU3iQNHcIY2P6GlPCr8iScJV8I4S5hRU6sSQpNOKCLi5Q0VcdMEYa6b6vfNMXyqXI9IFzG44SE+RaxrN+5+ROw==} engines: {node: '>=18'} - '@cacheable/utils@2.3.2': - resolution: {integrity: sha512-8kGE2P+HjfY8FglaOiW+y8qxcaQAfAhVML+i66XJR3YX5FtyDqn6Txctr3K2FrbxLKixRRYYBWMbuGciOhYNDg==} + '@cacheable/utils@2.2.0': + resolution: {integrity: sha512-7xaQayO3msdVcxXLYcLU5wDqJBNdQcPPPHr6mdTEIQI7N7TbtSVVTpWOTfjyhg0L6AQwQdq7miKdWtTDBoBldQ==} '@chatscope/chat-ui-kit-react@2.1.1': resolution: {integrity: sha512-rCtE9abdmAbBDkAAUYBC1TDTBMZHquqFIZhADptAfHcJ8z8W3XH/z/ZuwBSJXtzi6h1mwCNc3tBmm1A2NLGhNg==} @@ -817,11 +802,11 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@emnapi/core@1.7.1': - resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} + '@emnapi/core@1.7.0': + resolution: {integrity: sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==} - '@emnapi/runtime@1.7.1': - resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + '@emnapi/runtime@1.7.0': + resolution: {integrity: sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==} '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} @@ -888,158 +873,158 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.27.2': - resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.27.2': - resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.27.2': - resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.27.2': - resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.27.2': - resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.27.2': - resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.27.2': - resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.2': - resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.27.2': - resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.27.2': - resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.27.2': - resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.27.2': - resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.27.2': - resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.27.2': - resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.27.2': - resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.27.2': - resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.27.2': - resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.27.2': - resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.2': - resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.27.2': - resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.2': - resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.27.2': - resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.27.2': - resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.27.2': - resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.27.2': - resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.27.2': - resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1070,12 +1055,12 @@ packages: resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.3': - resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.39.2': - resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} + '@eslint/js@9.39.1': + resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': @@ -1108,7 +1093,6 @@ packages: '@fortawesome/react-fontawesome@0.2.6': resolution: {integrity: sha512-mtBFIi1UsYQo7rYonYFkjgYKGoL8T+fEH6NGUpvuqtY3ytMsAoDaPo5rk25KuMtKDipY4bGYM/CkmCHA1N3FUg==} - deprecated: v0.2.x is no longer supported. Unless you are still using FontAwesome 5, please update to v3.1.1 or greater. peerDependencies: '@fortawesome/fontawesome-svg-core': ~1 || ~6 || ~7 react: 19.2.0 @@ -1154,8 +1138,8 @@ packages: '@hapi/content@6.0.0': resolution: {integrity: sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==} - '@hapi/cryptiles@6.0.3': - resolution: {integrity: sha512-r6VKalpbMHz4ci3gFjFysBmhwCg70RpYZy6OkjEpdXzAYnYFX5XsW7n4YMJvuIYpnMwLxGUjK/cBhA7X3JDvXw==} + '@hapi/cryptiles@6.0.1': + resolution: {integrity: sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ==} engines: {node: '>=14.0.0'} '@hapi/file@3.0.0': @@ -1519,11 +1503,11 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@keyv/bigmap@1.3.0': - resolution: {integrity: sha512-KT01GjzV6AQD5+IYrcpoYLkCu1Jod3nau1Z7EsEuViO3TZGRacSbO9MfHmbJ1WaOXFtWLxPVj169cn2WNKPkIg==} + '@keyv/bigmap@1.1.0': + resolution: {integrity: sha512-MX7XIUNwVRK+hjZcAbNJ0Z8DREo+Weu9vinBOjGU1thEi9F6vPhICzBbk4CCf3eEefKRz7n6TfZXwUFZTSgj8Q==} engines: {node: '>= 18'} peerDependencies: - keyv: ^5.5.4 + keyv: ^5.5.3 '@keyv/serialize@1.1.1': resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} @@ -1631,8 +1615,8 @@ packages: '@types/react': optional: true - '@mui/types@7.4.9': - resolution: {integrity: sha512-dNO8Z9T2cujkSIaCnWwprfeKmTWh97cnjkgmpFJ2sbfXLx8SMZijCYHOtP/y5nnUb/Rm2omxbDMmtUoSaUtKaw==} + '@mui/types@7.4.8': + resolution: {integrity: sha512-ZNXLBjkPV6ftLCmmRCafak3XmSn8YV0tKE/ZOhzKys7TZXUiE0mZxlH8zKDo6j6TTUaDnuij68gIG+0Ucm7Xhw==} peerDependencies: '@types/react': 19.2.2 peerDependenciesMeta: @@ -1649,8 +1633,8 @@ packages: '@types/react': optional: true - '@mui/utils@7.3.6': - resolution: {integrity: sha512-jn+Ba02O6PiFs7nKva8R2aJJ9kJC+3kQ2R0BbKNY3KQQ36Qng98GnPRFTlbwYTdMD6hLEBKaMLUktyg/rTfd2w==} + '@mui/utils@7.3.5': + resolution: {integrity: sha512-jisvFsEC3sgjUjcPnR4mYfhzjCDIudttSGSbe1o/IXFNu0kZuR+7vqQI0jg8qtcVZBHWrwTfvAZj9MNMumcq1g==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': 19.2.2 @@ -1659,8 +1643,8 @@ packages: '@types/react': optional: true - '@mui/x-data-grid-pro@7.29.12': - resolution: {integrity: sha512-HoBaqJYqxaVZCkv3NK1qdca0Sv2er6L2Wrt51gyfMBBuM+liSpQ0L4HqX42bzIst+ScAoBpBAn6ILm9RQ0rqLw==} + '@mui/x-data-grid-pro@7.29.9': + resolution: {integrity: sha512-ulh/hvvSboZZfHS+ajM0rtRTsBAmQEh519GHjkFfyTdn94o6a+4pFhhuBFN0toyj6264HV0NLs5FJp/zx+bEwA==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.9.0 @@ -1675,8 +1659,8 @@ packages: '@emotion/styled': optional: true - '@mui/x-data-grid@7.29.12': - resolution: {integrity: sha512-MaEC7ubr/je8jVWjdRU7LxBXAzlOZwFEdNdvlDUJIYkRa3TRCQ1HsY8Gd8Od0jnlnMYn9M4BrEfOrq9VRnt4bw==} + '@mui/x-data-grid@7.29.9': + resolution: {integrity: sha512-RfK7Fnuu4eyv/4eD3MEB1xxZsx0xRBsofb1kifghIjyQV1EKAeRcwvczyrzQggj7ZRT5AqkwCzhLsZDvE5O0nQ==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.9.0 @@ -1787,8 +1771,8 @@ packages: axios: ^1.3.1 rxjs: ^7.0.0 - '@nestjs/common@11.1.9': - resolution: {integrity: sha512-zDntUTReRbAThIfSp3dQZ9kKqI+LjgLp5YZN5c1bgNRDuoeLySAoZg46Bg1a+uV8TMgIRziHocglKGNzr6l+bQ==} + '@nestjs/common@11.1.6': + resolution: {integrity: sha512-krKwLLcFmeuKDqngG2N/RuZHCs2ycsKcxWIDgcm7i1lf3sQ0iG03ci+DsP/r3FcT/eJDFsIHnKtNta2LIi7PzQ==} peerDependencies: class-transformer: '>=0.4.1' class-validator: '>=0.13.2' @@ -1800,8 +1784,8 @@ packages: class-validator: optional: true - '@nestjs/core@11.1.9': - resolution: {integrity: sha512-a00B0BM4X+9z+t3UxJqIZlemIwCQdYoPKrMcM+ky4z3pkqqG1eTWexjs+YXpGObnLnjtMPVKWlcZHp3adDYvUw==} + '@nestjs/core@11.1.6': + resolution: {integrity: sha512-siWX7UDgErisW18VTeJA+x+/tpNZrJewjTBsRPF3JVxuWRuAB1kRoiJcxHgln8Lb5UY9NdvklITR84DUEXD0Cg==} engines: {node: '>= 20'} peerDependencies: '@nestjs/common': ^11.0.0 @@ -1818,53 +1802,53 @@ packages: '@nestjs/websockets': optional: true - '@next/env@15.5.9': - resolution: {integrity: sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==} + '@next/env@15.5.4': + resolution: {integrity: sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==} - '@next/swc-darwin-arm64@15.5.7': - resolution: {integrity: sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==} + '@next/swc-darwin-arm64@15.5.4': + resolution: {integrity: sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.5.7': - resolution: {integrity: sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==} + '@next/swc-darwin-x64@15.5.4': + resolution: {integrity: sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.5.7': - resolution: {integrity: sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==} + '@next/swc-linux-arm64-gnu@15.5.4': + resolution: {integrity: sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.5.7': - resolution: {integrity: sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==} + '@next/swc-linux-arm64-musl@15.5.4': + resolution: {integrity: sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.5.7': - resolution: {integrity: sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==} + '@next/swc-linux-x64-gnu@15.5.4': + resolution: {integrity: sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.5.7': - resolution: {integrity: sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==} + '@next/swc-linux-x64-musl@15.5.4': + resolution: {integrity: sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.5.7': - resolution: {integrity: sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==} + '@next/swc-win32-arm64-msvc@15.5.4': + resolution: {integrity: sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.5.7': - resolution: {integrity: sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==} + '@next/swc-win32-x64-msvc@15.5.4': + resolution: {integrity: sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1872,6 +1856,18 @@ packages: '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + '@nuxt/opencollective@0.4.1': resolution: {integrity: sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==} engines: {node: ^14.18.0 || >=16.10.0, npm: '>=5.10.0'} @@ -1882,8 +1878,8 @@ packages: engines: {node: '>=8.0.0', npm: '>=5.0.0'} hasBin: true - '@openapitools/openapi-generator-cli@2.25.2': - resolution: {integrity: sha512-TXElbW1NXCy0EECXiO5AD2ZzT1dmaCs41Z8t3pBUGaJf8zgF/Lm0P6GRhVEpw29iHBNjZcy8nrgQ1acUfuCdng==} + '@openapitools/openapi-generator-cli@2.25.0': + resolution: {integrity: sha512-u/3VAbF8c68AXBgm8nBAdDPLPW/KgrtHz28yemf92zNB0iDZFGdRUX2W80Lzf177g6ctYLz0GIPHCOU0LTJegQ==} engines: {node: '>=16'} hasBin: true @@ -1934,121 +1930,121 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@rollup/rollup-android-arm-eabi@4.53.5': - resolution: {integrity: sha512-iDGS/h7D8t7tvZ1t6+WPK04KD0MwzLZrG0se1hzBjSi5fyxlsiggoJHwh18PCFNn7tG43OWb6pdZ6Y+rMlmyNQ==} + '@rollup/rollup-android-arm-eabi@4.53.1': + resolution: {integrity: sha512-bxZtughE4VNVJlL1RdoSE545kc4JxL7op57KKoi59/gwuU5rV6jLWFXXc8jwgFoT6vtj+ZjO+Z2C5nrY0Cl6wA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.53.5': - resolution: {integrity: sha512-wrSAViWvZHBMMlWk6EJhvg8/rjxzyEhEdgfMMjREHEq11EtJ6IP6yfcCH57YAEca2Oe3FNCE9DSTgU70EIGmVw==} + '@rollup/rollup-android-arm64@4.53.1': + resolution: {integrity: sha512-44a1hreb02cAAfAKmZfXVercPFaDjqXCK+iKeVOlJ9ltvnO6QqsBHgKVPTu+MJHSLLeMEUbeG2qiDYgbFPU48g==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.53.5': - resolution: {integrity: sha512-S87zZPBmRO6u1YXQLwpveZm4JfPpAa6oHBX7/ghSiGH3rz/KDgAu1rKdGutV+WUI6tKDMbaBJomhnT30Y2t4VQ==} + '@rollup/rollup-darwin-arm64@4.53.1': + resolution: {integrity: sha512-usmzIgD0rf1syoOZ2WZvy8YpXK5G1V3btm3QZddoGSa6mOgfXWkkv+642bfUUldomgrbiLQGrPryb7DXLovPWQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.5': - resolution: {integrity: sha512-YTbnsAaHo6VrAczISxgpTva8EkfQus0VPEVJCEaboHtZRIb6h6j0BNxRBOwnDciFTZLDPW5r+ZBmhL/+YpTZgA==} + '@rollup/rollup-darwin-x64@4.53.1': + resolution: {integrity: sha512-is3r/k4vig2Gt8mKtTlzzyaSQ+hd87kDxiN3uDSDwggJLUV56Umli6OoL+/YZa/KvtdrdyNfMKHzL/P4siOOmg==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.53.5': - resolution: {integrity: sha512-1T8eY2J8rKJWzaznV7zedfdhD1BqVs1iqILhmHDq/bqCUZsrMt+j8VCTHhP0vdfbHK3e1IQ7VYx3jlKqwlf+vw==} + '@rollup/rollup-freebsd-arm64@4.53.1': + resolution: {integrity: sha512-QJ1ksgp/bDJkZB4daldVmHaEQkG4r8PUXitCOC2WRmRaSaHx5RwPoI3DHVfXKwDkB+Sk6auFI/+JHacTekPRSw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.5': - resolution: {integrity: sha512-sHTiuXyBJApxRn+VFMaw1U+Qsz4kcNlxQ742snICYPrY+DDL8/ZbaC4DVIB7vgZmp3jiDaKA0WpBdP0aqPJoBQ==} + '@rollup/rollup-freebsd-x64@4.53.1': + resolution: {integrity: sha512-J6ma5xgAzvqsnU6a0+jgGX/gvoGokqpkx6zY4cWizRrm0ffhHDpJKQgC8dtDb3+MqfZDIqs64REbfHDMzxLMqQ==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.53.5': - resolution: {integrity: sha512-dV3T9MyAf0w8zPVLVBptVlzaXxka6xg1f16VAQmjg+4KMSTWDvhimI/Y6mp8oHwNrmnmVl9XxJ/w/mO4uIQONA==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.1': + resolution: {integrity: sha512-JzWRR41o2U3/KMNKRuZNsDUAcAVUYhsPuMlx5RUldw0E4lvSIXFUwejtYz1HJXohUmqs/M6BBJAUBzKXZVddbg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.53.5': - resolution: {integrity: sha512-wIGYC1x/hyjP+KAu9+ewDI+fi5XSNiUi9Bvg6KGAh2TsNMA3tSEs+Sh6jJ/r4BV/bx/CyWu2ue9kDnIdRyafcQ==} + '@rollup/rollup-linux-arm-musleabihf@4.53.1': + resolution: {integrity: sha512-L8kRIrnfMrEoHLHtHn+4uYA52fiLDEDyezgxZtGUTiII/yb04Krq+vk3P2Try+Vya9LeCE9ZHU8CXD6J9EhzHQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.53.5': - resolution: {integrity: sha512-Y+qVA0D9d0y2FRNiG9oM3Hut/DgODZbU9I8pLLPwAsU0tUKZ49cyV1tzmB/qRbSzGvY8lpgGkJuMyuhH7Ma+Vg==} + '@rollup/rollup-linux-arm64-gnu@4.53.1': + resolution: {integrity: sha512-ysAc0MFRV+WtQ8li8hi3EoFi7us6d1UzaS/+Dp7FYZfg3NdDljGMoVyiIp6Ucz7uhlYDBZ/zt6XI0YEZbUO11Q==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.53.5': - resolution: {integrity: sha512-juaC4bEgJsyFVfqhtGLz8mbopaWD+WeSOYr5E16y+1of6KQjc0BpwZLuxkClqY1i8sco+MdyoXPNiCkQou09+g==} + '@rollup/rollup-linux-arm64-musl@4.53.1': + resolution: {integrity: sha512-UV6l9MJpDbDZZ/fJvqNcvO1PcivGEf1AvKuTcHoLjVZVFeAMygnamCTDikCVMRnA+qJe+B3pSbgX2+lBMqgBhA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.53.5': - resolution: {integrity: sha512-rIEC0hZ17A42iXtHX+EPJVL/CakHo+tT7W0pbzdAGuWOt2jxDFh7A/lRhsNHBcqL4T36+UiAgwO8pbmn3dE8wA==} + '@rollup/rollup-linux-loong64-gnu@4.53.1': + resolution: {integrity: sha512-UDUtelEprkA85g95Q+nj3Xf0M4hHa4DiJ+3P3h4BuGliY4NReYYqwlc0Y8ICLjN4+uIgCEvaygYlpf0hUj90Yg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.53.5': - resolution: {integrity: sha512-T7l409NhUE552RcAOcmJHj3xyZ2h7vMWzcwQI0hvn5tqHh3oSoclf9WgTl+0QqffWFG8MEVZZP1/OBglKZx52Q==} + '@rollup/rollup-linux-ppc64-gnu@4.53.1': + resolution: {integrity: sha512-vrRn+BYhEtNOte/zbc2wAUQReJXxEx2URfTol6OEfY2zFEUK92pkFBSXRylDM7aHi+YqEPJt9/ABYzmcrS4SgQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.53.5': - resolution: {integrity: sha512-7OK5/GhxbnrMcxIFoYfhV/TkknarkYC1hqUw1wU2xUN3TVRLNT5FmBv4KkheSG2xZ6IEbRAhTooTV2+R5Tk0lQ==} + '@rollup/rollup-linux-riscv64-gnu@4.53.1': + resolution: {integrity: sha512-gto/1CxHyi4A7YqZZNznQYrVlPSaodOBPKM+6xcDSCMVZN/Fzb4K+AIkNz/1yAYz9h3Ng+e2fY9H6bgawVq17w==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.53.5': - resolution: {integrity: sha512-GwuDBE/PsXaTa76lO5eLJTyr2k8QkPipAyOrs4V/KJufHCZBJ495VCGJol35grx9xryk4V+2zd3Ri+3v7NPh+w==} + '@rollup/rollup-linux-riscv64-musl@4.53.1': + resolution: {integrity: sha512-KZ6Vx7jAw3aLNjFR8eYVcQVdFa/cvBzDNRFM3z7XhNNunWjA03eUrEwJYPk0G8V7Gs08IThFKcAPS4WY/ybIrQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.53.5': - resolution: {integrity: sha512-IAE1Ziyr1qNfnmiQLHBURAD+eh/zH1pIeJjeShleII7Vj8kyEm2PF77o+lf3WTHDpNJcu4IXJxNO0Zluro8bOw==} + '@rollup/rollup-linux-s390x-gnu@4.53.1': + resolution: {integrity: sha512-HvEixy2s/rWNgpwyKpXJcHmE7om1M89hxBTBi9Fs6zVuLU4gOrEMQNbNsN/tBVIMbLyysz/iwNiGtMOpLAOlvA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.53.5': - resolution: {integrity: sha512-Pg6E+oP7GvZ4XwgRJBuSXZjcqpIW3yCBhK4BcsANvb47qMvAbCjR6E+1a/U2WXz1JJxp9/4Dno3/iSJLcm5auw==} + '@rollup/rollup-linux-x64-gnu@4.53.1': + resolution: {integrity: sha512-E/n8x2MSjAQgjj9IixO4UeEUeqXLtiA7pyoXCFYLuXpBA/t2hnbIdxHfA7kK9BFsYAoNU4st1rHYdldl8dTqGA==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.53.5': - resolution: {integrity: sha512-txGtluxDKTxaMDzUduGP0wdfng24y1rygUMnmlUJ88fzCCULCLn7oE5kb2+tRB+MWq1QDZT6ObT5RrR8HFRKqg==} + '@rollup/rollup-linux-x64-musl@4.53.1': + resolution: {integrity: sha512-IhJ087PbLOQXCN6Ui/3FUkI9pWNZe/Z7rEIVOzMsOs1/HSAECCvSZ7PkIbkNqL/AZn6WbZvnoVZw/qwqYMo4/w==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.53.5': - resolution: {integrity: sha512-3DFiLPnTxiOQV993fMc+KO8zXHTcIjgaInrqlG8zDp1TlhYl6WgrOHuJkJQ6M8zHEcntSJsUp1XFZSY8C1DYbg==} + '@rollup/rollup-openharmony-arm64@4.53.1': + resolution: {integrity: sha512-0++oPNgLJHBblreu0SFM7b3mAsBJBTY0Ksrmu9N6ZVrPiTkRgda52mWR7TKhHAsUb9noCjFvAw9l6ZO1yzaVbA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.53.5': - resolution: {integrity: sha512-nggc/wPpNTgjGg75hu+Q/3i32R00Lq1B6N1DO7MCU340MRKL3WZJMjA9U4K4gzy3dkZPXm9E1Nc81FItBVGRlA==} + '@rollup/rollup-win32-arm64-msvc@4.53.1': + resolution: {integrity: sha512-VJXivz61c5uVdbmitLkDlbcTk9Or43YC2QVLRkqp86QoeFSqI81bNgjhttqhKNMKnQMWnecOCm7lZz4s+WLGpQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.5': - resolution: {integrity: sha512-U/54pTbdQpPLBdEzCT6NBCFAfSZMvmjr0twhnD9f4EIvlm9wy3jjQ38yQj1AGznrNO65EWQMgm/QUjuIVrYF9w==} + '@rollup/rollup-win32-ia32-msvc@4.53.1': + resolution: {integrity: sha512-NmZPVTUOitCXUH6erJDzTQ/jotYw4CnkMDjCYRxNHVD9bNyfrGoIse684F9okwzKCV4AIHRbUkeTBc9F2OOH5Q==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.5': - resolution: {integrity: sha512-2NqKgZSuLH9SXBBV2dWNRCZmocgSOx8OJSdpRaEcRlIfX8YrKxUT6z0F1NpvDVhOsl190UFTRh2F2WDWWCYp3A==} + '@rollup/rollup-win32-x64-gnu@4.53.1': + resolution: {integrity: sha512-2SNj7COIdAf6yliSpLdLG8BEsp5lgzRehgfkP0Av8zKfQFKku6JcvbobvHASPJu4f3BFxej5g+HuQPvqPhHvpQ==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.53.5': - resolution: {integrity: sha512-JRpZUhCfhZ4keB5v0fe02gQJy05GqboPOaxvjugW04RLSYYoB/9t2lx2u/tMs/Na/1NXfY8QYjgRljRpN+MjTQ==} + '@rollup/rollup-win32-x64-msvc@4.53.1': + resolution: {integrity: sha512-rLarc1Ofcs3DHtgSzFO31pZsCh8g05R2azN1q3fF+H423Co87My0R+tazOEvYVKXSLh8C4LerMK41/K7wlklcg==} cpu: [x64] os: [win32] '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@rushstack/eslint-patch@1.15.0': - resolution: {integrity: sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==} + '@rushstack/eslint-patch@1.14.1': + resolution: {integrity: sha512-jGTk8UD/RdjsNZW8qq10r0RBvxL8OWtoT+kImlzPDFilmozzM+9QmIJsmze9UiSBrFU45ZxhTYBypn9q9z/VfQ==} '@sinclair/typebox@0.34.41': resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} @@ -2062,12 +2058,8 @@ packages: '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@tokenizer/inflate@0.3.1': - resolution: {integrity: sha512-4oeoZEBQdLdt5WmP/hx1KZ6D3/Oid/0cUb2nk4F0pTDAWy+KCH3/EnAkZF/bvckWo8I33EqBm01lIPgmgc8rCA==} - engines: {node: '>=18'} - - '@tokenizer/inflate@0.4.1': - resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + '@tokenizer/inflate@0.2.7': + resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} engines: {node: '>=18'} '@tokenizer/token@0.3.0': @@ -2076,8 +2068,8 @@ packages: '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - '@tsconfig/node10@1.0.12': - resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} @@ -2120,8 +2112,8 @@ packages: peerDependencies: '@types/react': 19.2.2 - '@types/interpret@1.1.4': - resolution: {integrity: sha512-r+tPKWHYqaxJOYA3Eik0mMi+SEREqOXLmsooRFmc6GHv7nWUDixFtKN+cegvsPlDcEZd9wxsdp041v2imQuvag==} + '@types/interpret@1.1.3': + resolution: {integrity: sha512-uBaBhj/BhilG58r64mtDb/BEdH51HIQLgP5bmWzc5qCtFMja8dCk/IOJmk36j0lbi9QHwI6sbtUNGuqXdKCAtQ==} '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -2144,27 +2136,23 @@ packages: '@types/long@4.0.2': resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} - '@types/long@5.0.0': - resolution: {integrity: sha512-eQs9RsucA/LNjnMoJvWG/nXa7Pot/RbBzilF/QRIU/xRl+0ApxrSUFsV5lmf01SvSlqMzJ7Zwxe440wmz2SJGA==} - deprecated: This is a stub types definition. long provides its own type definitions, so you do not need this installed. - '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} '@types/node@10.17.60': resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} - '@types/node@22.19.3': - resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==} + '@types/node@22.19.0': + resolution: {integrity: sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==} - '@types/node@24.10.4': - resolution: {integrity: sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==} + '@types/node@24.10.0': + resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/pg@8.16.0': - resolution: {integrity: sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==} + '@types/pg@8.15.6': + resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} @@ -2191,66 +2179,66 @@ packages: '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - '@types/yargs@17.0.35': - resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + '@types/yargs@17.0.34': + resolution: {integrity: sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==} - '@typescript-eslint/eslint-plugin@8.50.0': - resolution: {integrity: sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==} + '@typescript-eslint/eslint-plugin@8.46.3': + resolution: {integrity: sha512-sbaQ27XBUopBkRiuY/P9sWGOWUW4rl8fDoHIUmLpZd8uldsTyB4/Zg6bWTegPoTLnKj9Hqgn3QD6cjPNB32Odw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.50.0 + '@typescript-eslint/parser': ^8.46.3 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.50.0': - resolution: {integrity: sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==} + '@typescript-eslint/parser@8.46.3': + resolution: {integrity: sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.50.0': - resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==} + '@typescript-eslint/project-service@8.46.3': + resolution: {integrity: sha512-Fz8yFXsp2wDFeUElO88S9n4w1I4CWDTXDqDr9gYvZgUpwXQqmZBr9+NTTql5R3J7+hrJZPdpiWaB9VNhAKYLuQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.50.0': - resolution: {integrity: sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==} + '@typescript-eslint/scope-manager@8.46.3': + resolution: {integrity: sha512-FCi7Y1zgrmxp3DfWfr+3m9ansUUFoy8dkEdeQSgA9gbm8DaHYvZCdkFRQrtKiedFf3Ha6VmoqoAaP68+i+22kg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.50.0': - resolution: {integrity: sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==} + '@typescript-eslint/tsconfig-utils@8.46.3': + resolution: {integrity: sha512-GLupljMniHNIROP0zE7nCcybptolcH8QZfXOpCfhQDAdwJ/ZTlcaBOYebSOZotpti/3HrHSw7D3PZm75gYFsOA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.50.0': - resolution: {integrity: sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==} + '@typescript-eslint/type-utils@8.46.3': + resolution: {integrity: sha512-ZPCADbr+qfz3aiTTYNNkCbUt+cjNwI/5McyANNrFBpVxPt7GqpEYz5ZfdwuFyGUnJ9FdDXbGODUu6iRCI6XRXw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.50.0': - resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==} + '@typescript-eslint/types@8.46.3': + resolution: {integrity: sha512-G7Ok9WN/ggW7e/tOf8TQYMaxgID3Iujn231hfi0Pc7ZheztIJVpO44ekY00b7akqc6nZcvregk0Jpah3kep6hA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.50.0': - resolution: {integrity: sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==} + '@typescript-eslint/typescript-estree@8.46.3': + resolution: {integrity: sha512-f/NvtRjOm80BtNM5OQtlaBdM5BRFUv7gf381j9wygDNL+qOYSNOgtQ/DCndiYi80iIOv76QqaTmp4fa9hwI0OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.50.0': - resolution: {integrity: sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==} + '@typescript-eslint/utils@8.46.3': + resolution: {integrity: sha512-VXw7qmdkucEx9WkmR3ld/u6VhRyKeiF1uxWwCy/iuNfokjJ7VhsgLSOTjsol8BunSw190zABzpwdNsze2Kpo4g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.50.0': - resolution: {integrity: sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==} + '@typescript-eslint/visitor-keys@8.46.3': + resolution: {integrity: sha512-uk574k8IU0rOF/AjniX8qbLSGURJVUCeM5e4MIMKBFFi8weeiLrG1fyQejyLXQpRZbU/1BuQasleV/RfHC3hHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': @@ -2351,8 +2339,8 @@ packages: cpu: [x64] os: [win32] - '@whiskeysockets/baileys@6.7.21': - resolution: {integrity: sha512-xx9OHd6jlPiu5yZVuUdwEgFNAOXiEG8sULHxC6XfzNwssnwxnA9Lp44pR05H621GQcKyCfsH33TGy+Na6ygX4w==} + '@whiskeysockets/baileys@7.0.0-rc.9': + resolution: {integrity: sha512-YFm5gKXfDP9byCXCW3OPHKXLzrAKzolzgVUlRosHHgwbnf2YOO3XknkMm6J7+F0ns8OA0uuSBhgkRHTDtqkacw==} engines: {node: '>=20.0.0'} peerDependencies: audio-decode: ^2.1.3 @@ -2488,6 +2476,9 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axios@1.12.2: + resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} + axios@1.13.2: resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} @@ -2526,8 +2517,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.9.10: - resolution: {integrity: sha512-2VIKvDx8Z1a9rTB2eCkdPE5nSe28XnA+qivGnWHoB40hMMt/h1hSz0960Zqsn6ZyxWXUie0EBdElKv8may20AA==} + baseline-browser-mapping@2.8.25: + resolution: {integrity: sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==} hasBin: true basic-ftp@5.0.5: @@ -2550,8 +2541,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + browserslist@4.27.0: + resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -2584,8 +2575,8 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - cacheable@2.3.1: - resolution: {integrity: sha512-yr+FSHWn1ZUou5LkULX/S+jhfgfnLbuKQjE40tyEd4fxGZVMbBL5ifno0J0OauykS8UiCSgHi+DV/YD+rjFxFg==} + cacheable@2.1.1: + resolution: {integrity: sha512-LmF4AXiSNdiRbI2UjH8pAp9NIXxeQsTotpEaegPiDcnN0YPygDJDV3l/Urc0mL72JWdATEorKqIHEx55nDlONg==} call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} @@ -2611,8 +2602,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001761: - resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==} + caniuse-lite@1.0.30001754: + resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -2755,12 +2746,12 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - cookie@1.1.1: - resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} - core-js-compat@3.47.0: - resolution: {integrity: sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==} + core-js-compat@3.46.0: + resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -2792,8 +2783,8 @@ packages: resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} engines: {node: '>= 6'} - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} curve25519-js@0.0.4: resolution: {integrity: sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==} @@ -2840,8 +2831,8 @@ packages: supports-color: optional: true - dedent@1.7.1: - resolution: {integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==} + dedent@1.7.0: + resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -2950,8 +2941,8 @@ packages: ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - electron-to-chromium@1.5.267: - resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + electron-to-chromium@1.5.249: + resolution: {integrity: sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -2977,8 +2968,8 @@ packages: error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - es-abstract@1.24.1: - resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} + es-abstract@1.24.0: + resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} engines: {node: '>= 0.4'} es-define-property@1.0.1: @@ -3005,8 +2996,8 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - esbuild@0.27.2: - resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} hasBin: true @@ -3089,8 +3080,8 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-jest@29.5.0: - resolution: {integrity: sha512-DAi9H8xN/TUuNOt+xDP1RqpCJLsSxBb5u1zXSpCyp0VAWGL8MBAg5t7/Dk+76iX7d1LhWu4DDH77IQNUolLDyg==} + eslint-plugin-jest@29.0.1: + resolution: {integrity: sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==} engines: {node: ^20.12.0 || ^22.0.0 || >=24.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': ^8.0.0 @@ -3134,8 +3125,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.39.2: - resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} + eslint@9.39.1: + resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -3173,6 +3164,9 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -3185,12 +3179,16 @@ packages: resolution: {integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - fast-copy@4.0.2: - resolution: {integrity: sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw==} + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -3200,6 +3198,9 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} @@ -3223,12 +3224,8 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - file-type@21.1.0: - resolution: {integrity: sha512-boU4EHmP3JXkwDo4uhyBhTt5pPstxB6eEXKJBu2yu2l7aAMMm7QQYQEzssJmKReZYrFdFOJS8koVo6bXIBGDqA==} - engines: {node: '>=20'} - - file-type@21.1.1: - resolution: {integrity: sha512-ifJXo8zUqbQ/bLbl9sFoqHNTNWbnPY1COImFfM6CCy7z+E+jC1eY9YfOKkx0fckIg+VljAy2/87T61fp0+eEkg==} + file-type@21.0.0: + resolution: {integrity: sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==} engines: {node: '>=20'} fill-range@7.1.1: @@ -3282,8 +3279,8 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} fs-extra@11.3.2: @@ -3347,23 +3344,23 @@ packages: resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} engines: {node: '>= 14'} + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.5.0: - resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true - glob@11.1.0: - resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + glob@11.0.3: + resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} engines: {node: 20 || >=22} hasBin: true - glob@13.0.0: - resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} - engines: {node: 20 || >=22} - glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -3387,6 +3384,9 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + graphile-config@0.0.1-beta.18: resolution: {integrity: sha512-uMdF9Rt8/NwT1wVXNleYgM5ro2hHDodHiKA3efJhgdU8iP+r/hksnghOHreMva0sF5tV73f4TpiELPUR0g7O9w==} engines: {node: '>=16'} @@ -3396,8 +3396,8 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - graphql-request@7.4.0: - resolution: {integrity: sha512-xfr+zFb/QYbs4l4ty0dltqiXIp07U6sl+tOKAb0t50/EnQek6CVVBLjETXi+FghElytvgaAWtIOt3EV7zLzIAQ==} + graphql-request@7.3.1: + resolution: {integrity: sha512-GdinBsBVYrWzwEvOlzadrV5j8mdOc9ZT8In9QyRIZaxbhkTL08j35yNbPp96jAacYzjeD/hKKy2E2RGI7c7Yug==} peerDependencies: graphql: 14 - 16 @@ -3432,10 +3432,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hashery@1.3.0: - resolution: {integrity: sha512-fWltioiy5zsSAs9ouEnvhsVJeAXRybGCNNv0lvzpzNOSDbULXRy7ivFWwCCv4I5Am6kSo75hmbsCduOoc2/K4w==} - engines: {node: '>=20'} - hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -3446,8 +3442,8 @@ packages: hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - hookified@1.14.0: - resolution: {integrity: sha512-pi1ynXIMFx/uIIwpWJ/5CEtOHLGtnUB0WhGeeYT+fKcQ+WCQbm3/rrkAXnpfph++PgepNqPdTC2WTj8A6k6zoQ==} + hookified@1.12.2: + resolution: {integrity: sha512-aokUX1VdTpI0DUsndvW+OiwmBpKCu/NgRsSSkuSY0zq8PY6Q6a+lmOfAFDXAAOtBqJELvcWY9L1EVtzjbQcMdg==} html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -3475,8 +3471,8 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - iconv-lite@0.7.1: - resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} + iconv-lite@0.7.0: + resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} engines: {node: '>=0.10.0'} ieee754@1.2.1: @@ -3839,8 +3835,8 @@ packages: jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} - jose@6.1.3: - resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} + jose@6.1.1: + resolution: {integrity: sha512-GWSqjfOPf4cWOkBzw5THBjtGPhXKqYnfRBzh4Ni+ArTrQQ9unvmsA3oFLqaYKoKe5sjWmGu5wVKg9Ft1i+LQfg==} joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} @@ -3849,12 +3845,12 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.14.2: - resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true jsesc@3.0.2: @@ -3891,21 +3887,21 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - jsonwebtoken@9.0.3: - resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} + jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} - jwa@2.0.1: - resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + jwa@1.4.2: + resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} - jws@4.0.1: - resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - keyv@5.5.5: - resolution: {integrity: sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ==} + keyv@5.5.3: + resolution: {integrity: sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==} kysely@0.27.5: resolution: {integrity: sha512-s7hZHcQeSNKpzCkHRm8yA+0JPLjncSWnjb+2TIElwS2JAqYr+Kv3Ess+9KFfJS0C1xcQ1i9NkNHpWwCYpHMWsA==} @@ -3926,12 +3922,12 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - link-preview-js@3.2.0: - resolution: {integrity: sha512-FvrLltjOPGbTzt+RugbzM7g8XuUNLPO2U/INSLczrYdAA32E7nZVUrVL1gr61DGOArGJA2QkPGMEvNMLLsXREA==} + link-preview-js@3.1.0: + resolution: {integrity: sha512-hSvdHCy7tZJ8ohdgN5WcTBKaubpX7saYBzrSmNDDHnC7P6q+F4we+dwXuEr9LuplnkiGxkD4SaO4rrschfCZ2A==} engines: {node: '>=18'} - load-esm@1.0.3: - resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==} + load-esm@1.0.2: + resolution: {integrity: sha512-nVAvWk/jeyrWyXEAs84mpQCYccxRqgKY4OznLuJhJCa0XsPSfdOIr2zvBZEj3IHEHbX97jjscKRRV539bW0Gpw==} engines: {node: '>=13.2.0'} load-tsconfig@0.2.5: @@ -3976,6 +3972,9 @@ packages: lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -3996,8 +3995,8 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.2.4: - resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + lru-cache@11.2.2: + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -4035,6 +4034,10 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -4101,8 +4104,8 @@ packages: multipipe@1.0.2: resolution: {integrity: sha512-6uiC9OvY71vzSGX8lZvSqscE7ft9nPupJ8fMjrCNRAUy2LREUW42UL+V/NTrogr6rFgRydUrCX4ZitfpSNkSCQ==} - music-metadata@11.10.3: - resolution: {integrity: sha512-j0g/x4cNNZW6I5gdcPAY+GFkJY9WHTpkFDMBJKQLxJQyvSfQbXm57fTE3haGFFuOzCgtsTd4Plwc49Sn9RacDQ==} + music-metadata@11.10.0: + resolution: {integrity: sha512-alZYPjpqAPFgVZaFQob0PMq/9tSqaR+3m159vavrptxj09P0GcyBkDQI/wuCyn4uz/TDCrS8gN+9SzURlahmdQ==} engines: {node: '>=18'} mute-stream@0.0.8: @@ -4142,8 +4145,8 @@ packages: nodemailer: optional: true - next@15.5.9: - resolution: {integrity: sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==} + next@15.5.4: + resolution: {integrity: sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -4193,8 +4196,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - oauth4webapi@3.8.3: - resolution: {integrity: sha512-pQ5BsX3QRTgnt5HxgHwgunIRaDXBdkT23tf8dfzmtTIL2LTpdmxgbpbBm0VgFWAIDlezQvQCTgnVIUmHupXHxw==} + oauth4webapi@3.8.2: + resolution: {integrity: sha512-FzZZ+bht5X0FKe7Mwz3DAVAmlH1BV5blSak/lHMBKz0/EBMhX6B10GlQYI51+oRp8ObJaX0g6pXrAxZh5s8rjw==} oauth@0.9.15: resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} @@ -4284,6 +4287,14 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-queue@9.0.1: + resolution: {integrity: sha512-RhBdVhSwJb7Ocn3e8ULk4NMwBEuOxe+1zcgphUy9c2e5aR/xbEsdVXxHJ3lynw6Qiqu7OINEyHlZkiblEpaq7w==} + engines: {node: '>=20'} + + p-timeout@7.0.1: + resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==} + engines: {node: '>=20'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -4336,8 +4347,9 @@ packages: resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} engines: {node: 20 || >=22} - path-to-regexp@8.3.0: - resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} @@ -4394,11 +4406,8 @@ packages: pino-abstract-transport@2.0.0: resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} - pino-abstract-transport@3.0.0: - resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} - - pino-pretty@13.1.3: - resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==} + pino-pretty@13.1.2: + resolution: {integrity: sha512-3cN0tCakkT4f3zo9RXDIhy6GTvtYD6bK4CRBLN9j3E/ePqN1tugAXD5rGVfoChW6s0hiek+eyYlLNqc/BG7vBQ==} hasBin: true pino-std-serializers@7.0.0: @@ -4457,8 +4466,8 @@ packages: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} - postgres-bytea@1.0.1: - resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} + postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} engines: {node: '>=0.10.0'} postgres-date@1.0.7: @@ -4482,8 +4491,8 @@ packages: preact@10.24.3: resolution: {integrity: sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==} - preact@10.28.0: - resolution: {integrity: sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==} + preact@10.27.2: + resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -4533,8 +4542,8 @@ packages: pure-rand@7.0.1: resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} - qified@0.5.3: - resolution: {integrity: sha512-kXuQdQTB6oN3KhI6V4acnBSZx8D2I4xzZvn9+wFLLFCoBNQY/sFnCW6c43OL7pOQ2HvGV4lnWIXNmgfp7cTWhQ==} + qified@0.5.1: + resolution: {integrity: sha512-+BtFN3dCP+IaFA6IYNOu/f/uK1B8xD2QWyOeCse0rjtAebBmkzgd2d1OAXi3ikAzJMIBSdzZDNZ3wZKEUDQs5w==} engines: {node: '>=20'} qr.js@0.0.0: @@ -4549,6 +4558,9 @@ packages: engines: {node: '>=0.4.x'} deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} @@ -4573,8 +4585,8 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-is@19.2.3: - resolution: {integrity: sha512-qJNJfu81ByyabuG7hPFEbXqNcWSU3+eVus+KJs+0ncpGfMyYdvSmxiJxbWR65lYi1I+/0HBcliO029gc4F+PnA==} + react-is@19.2.0: + resolution: {integrity: sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==} react-polyglot@0.7.2: resolution: {integrity: sha512-d/075aofJ4of9wOSBewl+ViFkkM0L1DgE3RVDOXrHZ92w4o2643sTQJ6lSPw8wsJWFmlB/3Pvwm0UbGNvLfPBw==} @@ -4676,8 +4688,12 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} - rollup@4.53.5: - resolution: {integrity: sha512-iTNAbFSlRpcHeeWu73ywU/8KuU/LZmNCSxp6fjQkJBD3ivUb8tpDrXhIxEzA05HlYMEwmtaUnb3RP+YNv162OQ==} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.53.1: + resolution: {integrity: sha512-n2I0V0lN3E9cxxMqBCT3opWOiQBzRN7UG60z/WDKqdX2zHUS/39lezBcsckZFsV6fUTSnfqI7kHf60jDAPGKug==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -4685,6 +4701,9 @@ packages: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} @@ -4816,9 +4835,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - source-map@0.7.6: - resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} - engines: {node: '>= 12'} + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} @@ -4923,8 +4943,8 @@ packages: stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - sucrase@3.35.1: - resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true @@ -4985,6 +5005,9 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -5018,8 +5041,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsup@8.5.1: - resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + tsup@8.5.0: + resolution: {integrity: sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -5037,47 +5060,47 @@ packages: typescript: optional: true - tsx@4.21.0: - resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + tsx@4.20.6: + resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} engines: {node: '>=18.0.0'} hasBin: true - turbo-darwin-64@2.6.3: - resolution: {integrity: sha512-BlJJDc1CQ7SK5Y5qnl7AzpkvKSnpkfPmnA+HeU/sgny3oHZckPV2776ebO2M33CYDSor7+8HQwaodY++IINhYg==} + turbo-darwin-64@2.6.0: + resolution: {integrity: sha512-6vHnLAubHj8Ib45Knu+oY0ZVCLO7WcibzAvt5b1E72YHqAs4y8meMAGMZM0jLqWPh/9maHDc16/qBCMxtW4pXg==} cpu: [x64] os: [darwin] - turbo-darwin-arm64@2.6.3: - resolution: {integrity: sha512-MwVt7rBKiOK7zdYerenfCRTypefw4kZCue35IJga9CH1+S50+KTiCkT6LBqo0hHeoH2iKuI0ldTF2a0aB72z3w==} + turbo-darwin-arm64@2.6.0: + resolution: {integrity: sha512-IU+gWMEXNBw8H0pxvE7nPEa5p6yahxbN8g/Q4Bf0AHymsAFqsScgV0peeNbWybdmY9jk1LPbALOsF2kY1I7ZiQ==} cpu: [arm64] os: [darwin] - turbo-linux-64@2.6.3: - resolution: {integrity: sha512-cqpcw+dXxbnPtNnzeeSyWprjmuFVpHJqKcs7Jym5oXlu/ZcovEASUIUZVN3OGEM6Y/OTyyw0z09tOHNt5yBAVg==} + turbo-linux-64@2.6.0: + resolution: {integrity: sha512-CKoiJ2ZFJLCDsWdRlZg+ew1BkGn8iCEGdePhISVpjsGwkJwSVhVu49z2zKdBeL1IhcSKS2YALwp9ellNZANJxw==} cpu: [x64] os: [linux] - turbo-linux-arm64@2.6.3: - resolution: {integrity: sha512-MterpZQmjXyr4uM7zOgFSFL3oRdNKeflY7nsjxJb2TklsYqiu3Z9pQ4zRVFFH8n0mLGna7MbQMZuKoWqqHb45w==} + turbo-linux-arm64@2.6.0: + resolution: {integrity: sha512-WroVCdCvJbrhNxNdw7XB7wHAfPPJPV+IXY+ZKNed+9VdfBu/2mQNfKnvqTuFTH7n+Pdpv8to9qwhXRTJe26upg==} cpu: [arm64] os: [linux] - turbo-windows-64@2.6.3: - resolution: {integrity: sha512-biDU70v9dLwnBdLf+daoDlNJVvqOOP8YEjqNipBHzgclbQlXbsi6Gqqelp5er81Qo3BiRgmTNx79oaZQTPb07Q==} + turbo-windows-64@2.6.0: + resolution: {integrity: sha512-7pZo5aGQPR+A7RMtWCZHusarJ6y15LQ+o3jOmpMxTic/W6Bad+jSeqo07TWNIseIWjCVzrSv27+0odiYRYtQdA==} cpu: [x64] os: [win32] - turbo-windows-arm64@2.6.3: - resolution: {integrity: sha512-dDHVKpSeukah3VsI/xMEKeTnV9V9cjlpFSUs4bmsUiLu3Yv2ENlgVEZv65wxbeE0bh0jjpmElDT+P1KaCxArQQ==} + turbo-windows-arm64@2.6.0: + resolution: {integrity: sha512-1Ty+NwIksQY7AtFUCPrTpcKQE7zmd/f7aRjdT+qkqGFQjIjFYctEtN7qo4vpQPBgCfS1U3ka83A2u/9CfJQ3wQ==} cpu: [arm64] os: [win32] - turbo@2.6.3: - resolution: {integrity: sha512-bf6YKUv11l5Xfcmg76PyWoy/e2vbkkxFNBGJSnfdSXQC33ZiUfutYh6IXidc5MhsnrFkWfdNNLyaRk+kHMLlwA==} + turbo@2.6.0: + resolution: {integrity: sha512-kC5VJqOXo50k0/0jnJDDjibLAXalqT9j7PQ56so0pN+81VR4Fwb2QgIE9dTzT3phqOTQuEXkPh3sCpnv5Isz2g==} hasBin: true - twilio@5.11.1: - resolution: {integrity: sha512-LQuLrAwWk7dsu7S5JQWzLRe17qdD4/7OJcwZG6kYWMJILtxI7pXDHksu9DcIF/vKpSpL1F0/sA9uSF3xuVizMQ==} + twilio@5.10.4: + resolution: {integrity: sha512-5dUsT3/O1+WxyJop2a6a4r92NAgtEQL7+oSU4t466NPhDaPOOBH/uomxnYHD5GWouYo7CZ/B7XSOwlhEUAHpWg==} engines: {node: '>=14.0'} type-check@0.4.0: @@ -5148,8 +5171,8 @@ packages: unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -5191,9 +5214,15 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -5301,13 +5330,11 @@ packages: snapshots: - '@adiwajshing/keyed-db@0.2.4': {} - '@auth/core@0.41.1': dependencies: '@panva/hkdf': 1.2.1 - jose: 6.1.3 - oauth4webapi: 3.8.3 + jose: 6.1.1 + oauth4webapi: 3.8.2 preact: 10.24.3 preact-render-to-string: 6.5.11(preact@10.24.3) @@ -5348,11 +5375,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/eslint-parser@7.28.4(@babel/core@7.28.5)(eslint@9.39.2)': + '@babel/eslint-parser@7.28.4(@babel/core@7.28.5)(eslint@9.39.1)': dependencies: '@babel/core': 7.28.5 '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 9.39.2 + eslint: 9.39.1 eslint-visitor-keys: 2.1.0 semver: 6.3.1 @@ -5368,7 +5395,7 @@ snapshots: dependencies: '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 + browserslist: 4.27.0 lru-cache: 5.1.1 semver: 6.3.1 @@ -5523,23 +5550,26 @@ snapshots: '@borewit/text-codec@0.2.0': {} - '@cacheable/memory@2.0.6': + '@cacheable/memoize@2.0.3': dependencies: - '@cacheable/utils': 2.3.2 - '@keyv/bigmap': 1.3.0(keyv@5.5.5) - hookified: 1.14.0 - keyv: 5.5.5 + '@cacheable/utils': 2.2.0 - '@cacheable/node-cache@1.7.6': + '@cacheable/memory@2.0.4': dependencies: - cacheable: 2.3.1 - hookified: 1.14.0 - keyv: 5.5.5 + '@cacheable/utils': 2.2.0 + '@keyv/bigmap': 1.1.0(keyv@5.5.3) + hookified: 1.12.2 + keyv: 5.5.3 - '@cacheable/utils@2.3.2': + '@cacheable/node-cache@1.7.4': dependencies: - hashery: 1.3.0 - keyv: 5.5.5 + cacheable: 2.1.1 + hookified: 1.12.2 + keyv: 5.5.3 + + '@cacheable/utils@2.2.0': + dependencies: + keyv: 5.5.3 '@chatscope/chat-ui-kit-react@2.1.1(prop-types@15.8.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: @@ -5559,13 +5589,13 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@emnapi/core@1.7.1': + '@emnapi/core@1.7.0': dependencies: '@emnapi/wasi-threads': 1.1.0 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.7.1': + '@emnapi/runtime@1.7.0': dependencies: tslib: 2.8.1 optional: true @@ -5629,7 +5659,7 @@ snapshots: '@emotion/memoize': 0.9.0 '@emotion/unitless': 0.10.0 '@emotion/utils': 1.4.2 - csstype: 3.2.3 + csstype: 3.1.3 '@emotion/server@11.11.0': dependencies: @@ -5665,87 +5695,87 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.27.2': + '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/android-arm64@0.27.2': + '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm@0.27.2': + '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-x64@0.27.2': + '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.27.2': + '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-x64@0.27.2': + '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.27.2': + '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.27.2': + '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/linux-arm64@0.27.2': + '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm@0.27.2': + '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-ia32@0.27.2': + '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-loong64@0.27.2': + '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-mips64el@0.27.2': + '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-ppc64@0.27.2': + '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.27.2': + '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-s390x@0.27.2': + '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-x64@0.27.2': + '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.27.2': + '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.27.2': + '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.27.2': + '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.27.2': + '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.27.2': + '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/sunos-x64@0.27.2': + '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/win32-arm64@0.27.2': + '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-ia32@0.27.2': + '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-x64@0.27.2': + '@esbuild/win32-x64@0.25.12': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2)': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': dependencies: - eslint: 9.39.2 + eslint: 9.39.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -5770,7 +5800,7 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.3': + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 debug: 4.4.3 @@ -5778,13 +5808,13 @@ snapshots: globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.1 + js-yaml: 4.1.0 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@9.39.2': {} + '@eslint/js@9.39.1': {} '@eslint/object-schema@2.1.7': {} @@ -5871,7 +5901,7 @@ snapshots: dependencies: '@hapi/boom': 10.0.1 - '@hapi/cryptiles@6.0.3': + '@hapi/cryptiles@6.0.1': dependencies: '@hapi/boom': 10.0.1 @@ -5913,7 +5943,7 @@ snapshots: '@hapi/b64': 6.0.1 '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 - '@hapi/cryptiles': 6.0.3 + '@hapi/cryptiles': 6.0.1 '@hapi/hoek': 11.0.7 '@hapi/mimos@7.0.1': @@ -5955,7 +5985,7 @@ snapshots: '@hapi/boom': 10.0.1 '@hapi/bounce': 3.0.2 '@hapi/bourne': 3.0.0 - '@hapi/cryptiles': 6.0.3 + '@hapi/cryptiles': 6.0.1 '@hapi/hoek': 11.0.7 '@hapi/iron': 7.0.1 '@hapi/validate': 2.0.1 @@ -6096,7 +6126,7 @@ snapshots: '@img/sharp-wasm32@0.34.5': dependencies: - '@emnapi/runtime': 1.7.1 + '@emnapi/runtime': 1.7.0 optional: true '@img/sharp-win32-arm64@0.34.5': @@ -6108,12 +6138,12 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true - '@inquirer/external-editor@1.0.3(@types/node@24.10.4)': + '@inquirer/external-editor@1.0.3(@types/node@24.10.0)': dependencies: chardet: 2.1.1 - iconv-lite: 0.7.1 + iconv-lite: 0.7.0 optionalDependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.0 '@ioredis/commands@1.4.0': {} @@ -6137,7 +6167,7 @@ snapshots: camelcase: 5.3.1 find-up: 4.1.0 get-package-type: 0.1.0 - js-yaml: 3.14.2 + js-yaml: 3.14.1 resolve-from: 5.0.0 '@istanbuljs/schema@0.1.3': {} @@ -6145,13 +6175,13 @@ snapshots: '@jest/console@30.2.0': dependencies: '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 chalk: 4.1.2 jest-message-util: 30.2.0 jest-util: 30.2.0 slash: 3.0.0 - '@jest/core@30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3))': + '@jest/core@30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3))': dependencies: '@jest/console': 30.2.0 '@jest/pattern': 30.0.1 @@ -6159,14 +6189,14 @@ snapshots: '@jest/test-result': 30.2.0 '@jest/transform': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 4.3.1 exit-x: 0.2.2 graceful-fs: 4.2.11 jest-changed-files: 30.2.0 - jest-config: 30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)) + jest-config: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) jest-haste-map: 30.2.0 jest-message-util: 30.2.0 jest-regex-util: 30.0.1 @@ -6193,7 +6223,7 @@ snapshots: dependencies: '@jest/fake-timers': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 jest-mock: 30.2.0 '@jest/expect-utils@30.2.0': @@ -6211,7 +6241,7 @@ snapshots: dependencies: '@jest/types': 30.2.0 '@sinonjs/fake-timers': 13.0.5 - '@types/node': 24.10.4 + '@types/node': 24.10.0 jest-message-util: 30.2.0 jest-mock: 30.2.0 jest-util: 30.2.0 @@ -6229,7 +6259,7 @@ snapshots: '@jest/pattern@30.0.1': dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.0 jest-regex-util: 30.0.1 '@jest/reporters@30.2.0': @@ -6240,11 +6270,11 @@ snapshots: '@jest/transform': 30.2.0 '@jest/types': 30.2.0 '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 24.10.4 + '@types/node': 24.10.0 chalk: 4.1.2 collect-v8-coverage: 1.0.3 exit-x: 0.2.2 - glob: 10.5.0 + glob: 10.4.5 graceful-fs: 4.2.11 istanbul-lib-coverage: 3.2.2 istanbul-lib-instrument: 6.0.3 @@ -6317,8 +6347,8 @@ snapshots: '@jest/schemas': 30.0.5 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 24.10.4 - '@types/yargs': 17.0.35 + '@types/node': 24.10.0 + '@types/yargs': 17.0.34 chalk: 4.1.2 '@jridgewell/gen-mapping@0.3.13': @@ -6345,11 +6375,10 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@keyv/bigmap@1.3.0(keyv@5.5.5)': + '@keyv/bigmap@1.1.0(keyv@5.5.3)': dependencies: - hashery: 1.3.0 - hookified: 1.14.0 - keyv: 5.5.5 + hookified: 1.12.2 + keyv: 5.5.3 '@keyv/serialize@1.1.1': {} @@ -6365,11 +6394,11 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - '@mui/material-nextjs@6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)': + '@mui/material-nextjs@6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/react': 11.14.0(@types/react@19.2.2)(react@19.2.0) - next: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + next: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 optionalDependencies: '@emotion/cache': 11.14.0 @@ -6386,11 +6415,11 @@ snapshots: '@popperjs/core': 2.11.8 '@types/react-transition-group': 4.4.12(@types/react@19.2.2) clsx: 2.1.1 - csstype: 3.2.3 + csstype: 3.1.3 prop-types: 15.8.1 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - react-is: 19.2.3 + react-is: 19.2.0 react-transition-group: 4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0) optionalDependencies: '@emotion/react': 11.14.0(@types/react@19.2.2)(react@19.2.0) @@ -6412,7 +6441,7 @@ snapshots: '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 '@emotion/sheet': 1.4.0 - csstype: 3.2.3 + csstype: 3.1.3 prop-types: 15.8.1 react: 19.2.0 optionalDependencies: @@ -6427,7 +6456,7 @@ snapshots: '@mui/types': 7.2.24(@types/react@19.2.2) '@mui/utils': 6.4.9(@types/react@19.2.2)(react@19.2.0) clsx: 2.1.1 - csstype: 3.2.3 + csstype: 3.1.3 prop-types: 15.8.1 react: 19.2.0 optionalDependencies: @@ -6439,7 +6468,7 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - '@mui/types@7.4.9(@types/react@19.2.2)': + '@mui/types@7.4.8(@types/react@19.2.2)': dependencies: '@babel/runtime': 7.28.4 optionalDependencies: @@ -6453,29 +6482,29 @@ snapshots: clsx: 2.1.1 prop-types: 15.8.1 react: 19.2.0 - react-is: 19.2.3 + react-is: 19.2.0 optionalDependencies: '@types/react': 19.2.2 - '@mui/utils@7.3.6(@types/react@19.2.2)(react@19.2.0)': + '@mui/utils@7.3.5(@types/react@19.2.2)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 - '@mui/types': 7.4.9(@types/react@19.2.2) + '@mui/types': 7.4.8(@types/react@19.2.2) '@types/prop-types': 15.7.15 clsx: 2.1.1 prop-types: 15.8.1 react: 19.2.0 - react-is: 19.2.3 + react-is: 19.2.0 optionalDependencies: '@types/react': 19.2.2 - '@mui/x-data-grid-pro@7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@mui/x-data-grid-pro@7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) - '@mui/utils': 7.3.6(@types/react@19.2.2)(react@19.2.0) - '@mui/x-data-grid': 7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) + '@mui/x-data-grid': 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) '@mui/x-license': 7.29.1(@types/react@19.2.2)(react@19.2.0) '@types/format-util': 1.0.4 @@ -6490,12 +6519,12 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@mui/x-data-grid@7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@mui/x-data-grid@7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) - '@mui/utils': 7.3.6(@types/react@19.2.2)(react@19.2.0) + '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) clsx: 2.1.1 prop-types: 15.8.1 @@ -6514,7 +6543,7 @@ snapshots: '@babel/runtime': 7.28.4 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) - '@mui/utils': 7.3.6(@types/react@19.2.2)(react@19.2.0) + '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) '@mui/x-date-pickers': 7.29.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(date-fns@4.1.0)(dayjs@1.11.19)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) '@mui/x-license': 7.29.1(@types/react@19.2.2)(react@19.2.0) @@ -6536,7 +6565,7 @@ snapshots: '@babel/runtime': 7.28.4 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) - '@mui/utils': 7.3.6(@types/react@19.2.2)(react@19.2.0) + '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) '@types/react-transition-group': 4.4.12(@types/react@19.2.2) clsx: 2.1.1 @@ -6555,7 +6584,7 @@ snapshots: '@mui/x-internals@7.29.0(@types/react@19.2.2)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 - '@mui/utils': 7.3.6(@types/react@19.2.2)(react@19.2.0) + '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) react: 19.2.0 transitivePeerDependencies: - '@types/react' @@ -6563,7 +6592,7 @@ snapshots: '@mui/x-license@7.29.1(@types/react@19.2.2)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 - '@mui/utils': 7.3.6(@types/react@19.2.2)(react@19.2.0) + '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) react: 19.2.0 transitivePeerDependencies: @@ -6571,22 +6600,22 @@ snapshots: '@napi-rs/wasm-runtime@0.2.12': dependencies: - '@emnapi/core': 1.7.1 - '@emnapi/runtime': 1.7.1 + '@emnapi/core': 1.7.0 + '@emnapi/runtime': 1.7.0 '@tybys/wasm-util': 0.10.1 optional: true - '@nestjs/axios@4.0.1(@nestjs/common@11.1.9(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.13.2)(rxjs@7.8.2)': + '@nestjs/axios@4.0.1(@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.12.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.9(reflect-metadata@0.2.2)(rxjs@7.8.2) - axios: 1.13.2 + '@nestjs/common': 11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2) + axios: 1.12.2 rxjs: 7.8.2 - '@nestjs/common@11.1.9(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - file-type: 21.1.0 + file-type: 21.0.0 iterare: 1.2.1 - load-esm: 1.0.3 + load-esm: 1.0.2 reflect-metadata: 0.2.2 rxjs: 7.8.2 tslib: 2.8.1 @@ -6594,48 +6623,60 @@ snapshots: transitivePeerDependencies: - supports-color - '@nestjs/core@11.1.9(@nestjs/common@11.1.9(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/core@11.1.6(@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.9(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nuxt/opencollective': 0.4.1 fast-safe-stringify: 2.1.1 iterare: 1.2.1 - path-to-regexp: 8.3.0 + path-to-regexp: 8.2.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 tslib: 2.8.1 uid: 2.0.2 - '@next/env@15.5.9': {} + '@next/env@15.5.4': {} - '@next/swc-darwin-arm64@15.5.7': + '@next/swc-darwin-arm64@15.5.4': optional: true - '@next/swc-darwin-x64@15.5.7': + '@next/swc-darwin-x64@15.5.4': optional: true - '@next/swc-linux-arm64-gnu@15.5.7': + '@next/swc-linux-arm64-gnu@15.5.4': optional: true - '@next/swc-linux-arm64-musl@15.5.7': + '@next/swc-linux-arm64-musl@15.5.4': optional: true - '@next/swc-linux-x64-gnu@15.5.7': + '@next/swc-linux-x64-gnu@15.5.4': optional: true - '@next/swc-linux-x64-musl@15.5.7': + '@next/swc-linux-x64-musl@15.5.4': optional: true - '@next/swc-win32-arm64-msvc@15.5.7': + '@next/swc-win32-arm64-msvc@15.5.4': optional: true - '@next/swc-win32-x64-msvc@15.5.7': + '@next/swc-win32-x64-msvc@15.5.4': optional: true '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': dependencies: eslint-scope: 5.1.1 + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + '@nuxt/opencollective@0.4.1': dependencies: consola: 3.4.2 @@ -6648,21 +6689,21 @@ snapshots: transitivePeerDependencies: - encoding - '@openapitools/openapi-generator-cli@2.25.2(@types/node@24.10.4)': + '@openapitools/openapi-generator-cli@2.25.0(@types/node@24.10.0)': dependencies: - '@nestjs/axios': 4.0.1(@nestjs/common@11.1.9(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.13.2)(rxjs@7.8.2) - '@nestjs/common': 11.1.9(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.9(@nestjs/common@11.1.9(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/axios': 4.0.1(@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.12.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nuxtjs/opencollective': 0.3.2 - axios: 1.13.2 + axios: 1.12.2 chalk: 4.1.2 commander: 8.3.0 compare-versions: 6.1.1 concurrently: 9.2.1 console.table: 0.10.0 fs-extra: 11.3.2 - glob: 13.0.0 - inquirer: 8.2.7(@types/node@24.10.4) + glob: 11.0.3 + inquirer: 8.2.7(@types/node@24.10.0) proxy-agent: 6.5.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 @@ -6712,75 +6753,75 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@rollup/rollup-android-arm-eabi@4.53.5': + '@rollup/rollup-android-arm-eabi@4.53.1': optional: true - '@rollup/rollup-android-arm64@4.53.5': + '@rollup/rollup-android-arm64@4.53.1': optional: true - '@rollup/rollup-darwin-arm64@4.53.5': + '@rollup/rollup-darwin-arm64@4.53.1': optional: true - '@rollup/rollup-darwin-x64@4.53.5': + '@rollup/rollup-darwin-x64@4.53.1': optional: true - '@rollup/rollup-freebsd-arm64@4.53.5': + '@rollup/rollup-freebsd-arm64@4.53.1': optional: true - '@rollup/rollup-freebsd-x64@4.53.5': + '@rollup/rollup-freebsd-x64@4.53.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.53.5': + '@rollup/rollup-linux-arm-gnueabihf@4.53.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.53.5': + '@rollup/rollup-linux-arm-musleabihf@4.53.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.53.5': + '@rollup/rollup-linux-arm64-gnu@4.53.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.53.5': + '@rollup/rollup-linux-arm64-musl@4.53.1': optional: true - '@rollup/rollup-linux-loong64-gnu@4.53.5': + '@rollup/rollup-linux-loong64-gnu@4.53.1': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.53.5': + '@rollup/rollup-linux-ppc64-gnu@4.53.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.53.5': + '@rollup/rollup-linux-riscv64-gnu@4.53.1': optional: true - '@rollup/rollup-linux-riscv64-musl@4.53.5': + '@rollup/rollup-linux-riscv64-musl@4.53.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.53.5': + '@rollup/rollup-linux-s390x-gnu@4.53.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.53.5': + '@rollup/rollup-linux-x64-gnu@4.53.1': optional: true - '@rollup/rollup-linux-x64-musl@4.53.5': + '@rollup/rollup-linux-x64-musl@4.53.1': optional: true - '@rollup/rollup-openharmony-arm64@4.53.5': + '@rollup/rollup-openharmony-arm64@4.53.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.53.5': + '@rollup/rollup-win32-arm64-msvc@4.53.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.53.5': + '@rollup/rollup-win32-ia32-msvc@4.53.1': optional: true - '@rollup/rollup-win32-x64-gnu@4.53.5': + '@rollup/rollup-win32-x64-gnu@4.53.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.53.5': + '@rollup/rollup-win32-x64-msvc@4.53.1': optional: true '@rtsao/scc@1.1.0': {} - '@rushstack/eslint-patch@1.15.0': {} + '@rushstack/eslint-patch@1.14.1': {} '@sinclair/typebox@0.34.41': {} @@ -6796,7 +6837,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@tokenizer/inflate@0.3.1': + '@tokenizer/inflate@0.2.7': dependencies: debug: 4.4.3 fflate: 0.8.2 @@ -6804,18 +6845,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@tokenizer/inflate@0.4.1': - dependencies: - debug: 4.4.3 - token-types: 6.1.1 - transitivePeerDependencies: - - supports-color - '@tokenizer/token@0.3.0': {} '@tootallnate/quickjs-emscripten@0.23.0': {} - '@tsconfig/node10@1.0.12': {} + '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -6857,7 +6891,7 @@ snapshots: '@types/fluent-ffmpeg@2.1.28': dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.0 '@types/format-util@1.0.4': {} @@ -6866,9 +6900,9 @@ snapshots: '@types/react': 19.2.2 hoist-non-react-statics: 3.3.2 - '@types/interpret@1.1.4': + '@types/interpret@1.1.3': dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.0 '@types/istanbul-lib-coverage@2.0.6': {} @@ -6891,27 +6925,23 @@ snapshots: '@types/long@4.0.2': {} - '@types/long@5.0.0': - dependencies: - long: 5.3.2 - '@types/ms@2.1.0': {} '@types/node@10.17.60': {} - '@types/node@22.19.3': + '@types/node@22.19.0': dependencies: undici-types: 6.21.0 - '@types/node@24.10.4': + '@types/node@24.10.0': dependencies: undici-types: 7.16.0 '@types/parse-json@4.0.2': {} - '@types/pg@8.16.0': + '@types/pg@8.15.6': dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.0 pg-protocol: 1.10.3 pg-types: 2.2.0 @@ -6927,7 +6957,7 @@ snapshots: '@types/react@19.2.2': dependencies: - csstype: 3.2.3 + csstype: 3.1.3 '@types/semver@7.7.1': {} @@ -6935,19 +6965,20 @@ snapshots: '@types/yargs-parser@21.0.3': {} - '@types/yargs@17.0.35': + '@types/yargs@17.0.34': dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 - eslint: 9.39.2 + '@typescript-eslint/parser': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.3 + '@typescript-eslint/type-utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.3 + eslint: 9.39.1 + graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.1.0(typescript@5.9.3) @@ -6955,79 +6986,80 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/scope-manager': 8.46.3 + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.3 debug: 4.4.3 - eslint: 9.39.2 + eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.50.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.46.3(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.9.3) + '@typescript-eslint/types': 8.46.3 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.50.0': + '@typescript-eslint/scope-manager@8.46.3': dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/visitor-keys': 8.46.3 - '@typescript-eslint/tsconfig-utils@8.50.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.46.3(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.46.3(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.2 + eslint: 9.39.1 ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.50.0': {} + '@typescript-eslint/types@8.46.3': {} - '@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.46.3(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.50.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/project-service': 8.46.3(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.9.3) + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/visitor-keys': 8.46.3 debug: 4.4.3 + fast-glob: 3.3.3 + is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.3 - tinyglobby: 0.2.15 ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/utils@8.46.3(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - eslint: 9.39.2 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@typescript-eslint/scope-manager': 8.46.3 + '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) + eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.50.0': + '@typescript-eslint/visitor-keys@8.46.3': dependencies: - '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/types': 8.46.3 eslint-visitor-keys: 4.2.1 '@ungap/structured-clone@1.3.0': {} @@ -7091,23 +7123,23 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@whiskeysockets/baileys@6.7.21(link-preview-js@3.2.0)(sharp@0.34.5)': + '@whiskeysockets/baileys@7.0.0-rc.9(link-preview-js@3.1.0)(sharp@0.34.5)': dependencies: - '@cacheable/node-cache': 1.7.6 + '@cacheable/node-cache': 1.7.4 '@hapi/boom': 9.1.4 async-mutex: 0.5.0 - axios: 1.13.2 libsignal: '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67' - music-metadata: 11.10.3 + lru-cache: 11.2.2 + music-metadata: 11.10.0 + p-queue: 9.0.1 pino: 9.14.0 protobufjs: 7.5.4 sharp: 0.34.5 ws: 8.18.3 optionalDependencies: - link-preview-js: 3.2.0 + link-preview-js: 3.1.0 transitivePeerDependencies: - bufferutil - - debug - supports-color - utf-8-validate @@ -7184,7 +7216,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 is-string: 1.1.1 @@ -7195,7 +7227,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -7204,14 +7236,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-shim-unscopables: 1.1.0 array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-shim-unscopables: 1.1.0 arraybuffer.prototype.slice@1.0.4: @@ -7219,7 +7251,7 @@ snapshots: array-buffer-byte-length: 1.0.2 call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 @@ -7244,10 +7276,18 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 + axios@1.12.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axios@1.13.2: dependencies: follow-redirects: 1.15.11 - form-data: 4.0.5 + form-data: 4.0.4 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug @@ -7314,7 +7354,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.9.10: {} + baseline-browser-mapping@2.8.25: {} basic-ftp@5.0.5: {} @@ -7324,7 +7364,8 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - boolbase@1.0.0: {} + boolbase@1.0.0: + optional: true brace-expansion@1.1.12: dependencies: @@ -7339,13 +7380,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.28.1: + browserslist@4.27.0: dependencies: - baseline-browser-mapping: 2.9.10 - caniuse-lite: 1.0.30001761 - electron-to-chromium: 1.5.267 + baseline-browser-mapping: 2.8.25 + caniuse-lite: 1.0.30001754 + electron-to-chromium: 1.5.249 node-releases: 2.0.27 - update-browserslist-db: 1.2.3(browserslist@4.28.1) + update-browserslist-db: 1.1.4(browserslist@4.27.0) bser@2.1.1: dependencies: @@ -7364,20 +7405,21 @@ snapshots: builtin-modules@5.0.0: {} - bundle-require@5.1.0(esbuild@0.27.2): + bundle-require@5.1.0(esbuild@0.25.12): dependencies: - esbuild: 0.27.2 + esbuild: 0.25.12 load-tsconfig: 0.2.5 cac@6.7.14: {} - cacheable@2.3.1: + cacheable@2.1.1: dependencies: - '@cacheable/memory': 2.0.6 - '@cacheable/utils': 2.3.2 - hookified: 1.14.0 - keyv: 5.5.5 - qified: 0.5.3 + '@cacheable/memoize': 2.0.3 + '@cacheable/memory': 2.0.4 + '@cacheable/utils': 2.2.0 + hookified: 1.12.2 + keyv: 5.5.3 + qified: 0.5.1 call-bind-apply-helpers@1.0.2: dependencies: @@ -7402,7 +7444,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001761: {} + caniuse-lite@1.0.30001754: {} chalk@4.1.2: dependencies: @@ -7423,6 +7465,7 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 domutils: 3.2.2 + optional: true cheerio@1.0.0-rc.11: dependencies: @@ -7434,6 +7477,7 @@ snapshots: parse5: 7.3.0 parse5-htmlparser2-tree-adapter: 7.1.0 tslib: 2.8.1 + optional: true chokidar@4.0.3: dependencies: @@ -7524,11 +7568,11 @@ snapshots: cookie@0.7.2: {} - cookie@1.1.1: {} + cookie@1.0.2: {} - core-js-compat@3.47.0: + core-js-compat@3.46.0: dependencies: - browserslist: 4.28.1 + browserslist: 4.27.0 core-util-is@1.0.3: {} @@ -7543,7 +7587,7 @@ snapshots: cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.1 - js-yaml: 4.1.1 + js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: @@ -7564,10 +7608,12 @@ snapshots: domhandler: 5.0.3 domutils: 3.2.2 nth-check: 2.1.1 + optional: true - css-what@6.2.2: {} + css-what@6.2.2: + optional: true - csstype@3.2.3: {} + csstype@3.1.3: {} curve25519-js@0.0.4: {} @@ -7605,7 +7651,7 @@ snapshots: dependencies: ms: 2.1.3 - dedent@1.7.1(babel-plugin-macros@3.1.0): + dedent@1.7.0(babel-plugin-macros@3.1.0): optionalDependencies: babel-plugin-macros: 3.1.0 @@ -7652,25 +7698,29 @@ snapshots: dom-helpers@5.2.1: dependencies: '@babel/runtime': 7.28.4 - csstype: 3.2.3 + csstype: 3.1.3 dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 entities: 4.5.0 + optional: true - domelementtype@2.3.0: {} + domelementtype@2.3.0: + optional: true domhandler@5.0.3: dependencies: domelementtype: 2.3.0 + optional: true domutils@3.2.2: dependencies: dom-serializer: 2.0.0 domelementtype: 2.3.0 domhandler: 5.0.3 + optional: true dotenv-cli@10.0.0: dependencies: @@ -7718,7 +7768,7 @@ snapshots: dependencies: safe-buffer: 5.2.1 - electron-to-chromium@1.5.267: {} + electron-to-chromium@1.5.249: {} emittery@0.13.1: {} @@ -7730,15 +7780,17 @@ snapshots: dependencies: once: 1.4.0 - entities@4.5.0: {} + entities@4.5.0: + optional: true - entities@6.0.1: {} + entities@6.0.1: + optional: true error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 - es-abstract@1.24.1: + es-abstract@1.24.0: dependencies: array-buffer-byte-length: 1.0.2 arraybuffer.prototype.slice: 1.0.4 @@ -7820,34 +7872,34 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild@0.27.2: + esbuild@0.25.12: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.2 - '@esbuild/android-arm': 0.27.2 - '@esbuild/android-arm64': 0.27.2 - '@esbuild/android-x64': 0.27.2 - '@esbuild/darwin-arm64': 0.27.2 - '@esbuild/darwin-x64': 0.27.2 - '@esbuild/freebsd-arm64': 0.27.2 - '@esbuild/freebsd-x64': 0.27.2 - '@esbuild/linux-arm': 0.27.2 - '@esbuild/linux-arm64': 0.27.2 - '@esbuild/linux-ia32': 0.27.2 - '@esbuild/linux-loong64': 0.27.2 - '@esbuild/linux-mips64el': 0.27.2 - '@esbuild/linux-ppc64': 0.27.2 - '@esbuild/linux-riscv64': 0.27.2 - '@esbuild/linux-s390x': 0.27.2 - '@esbuild/linux-x64': 0.27.2 - '@esbuild/netbsd-arm64': 0.27.2 - '@esbuild/netbsd-x64': 0.27.2 - '@esbuild/openbsd-arm64': 0.27.2 - '@esbuild/openbsd-x64': 0.27.2 - '@esbuild/openharmony-arm64': 0.27.2 - '@esbuild/sunos-x64': 0.27.2 - '@esbuild/win32-arm64': 0.27.2 - '@esbuild/win32-ia32': 0.27.2 - '@esbuild/win32-x64': 0.27.2 + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 escalade@3.2.0: {} @@ -7865,19 +7917,19 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@10.1.8(eslint@9.39.2): + eslint-config-prettier@10.1.8(eslint@9.39.1): dependencies: - eslint: 9.39.2 + eslint: 9.39.1 - eslint-config-xo-space@0.35.0(eslint@9.39.2): + eslint-config-xo-space@0.35.0(eslint@9.39.1): dependencies: - eslint: 9.39.2 - eslint-config-xo: 0.44.0(eslint@9.39.2) + eslint: 9.39.1 + eslint-config-xo: 0.44.0(eslint@9.39.1) - eslint-config-xo@0.44.0(eslint@9.39.2): + eslint-config-xo@0.44.0(eslint@9.39.1): dependencies: confusing-browser-globals: 1.0.11 - eslint: 9.39.2 + eslint: 9.39.1 eslint-import-resolver-node@0.3.9: dependencies: @@ -7887,23 +7939,23 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - eslint: 9.39.2 + '@typescript-eslint/parser': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + eslint: 9.39.1 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-eslint-comments@3.2.0(eslint@9.39.2): + eslint-plugin-eslint-comments@3.2.0(eslint@9.39.1): dependencies: escape-string-regexp: 1.0.5 - eslint: 9.39.2 + eslint: 9.39.1 ignore: 5.3.2 - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -7912,9 +7964,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.2 + eslint: 9.39.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -7926,38 +7978,38 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.3(eslint@9.39.1)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@29.5.0(@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(jest@30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)))(typescript@5.9.3): + eslint-plugin-jest@29.0.1(@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - eslint: 9.39.2 + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + eslint: 9.39.1 optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - jest: 30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)) + '@typescript-eslint/eslint-plugin': 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) + jest: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-promise@7.2.1(eslint@9.39.2): + eslint-plugin-promise@7.2.1(eslint@9.39.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) - eslint: 9.39.2 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + eslint: 9.39.1 - eslint-plugin-unicorn@61.0.2(eslint@9.39.2): + eslint-plugin-unicorn@61.0.2(eslint@9.39.1): dependencies: '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) '@eslint/plugin-kit': 0.3.5 change-case: 5.4.4 ci-info: 4.3.1 clean-regexp: 1.0.0 - core-js-compat: 3.47.0 - eslint: 9.39.2 + core-js-compat: 3.46.0 + eslint: 9.39.1 esquery: 1.6.0 find-up-simple: 1.0.1 globals: 16.5.0 @@ -7986,15 +8038,15 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.2: + eslint@9.39.1: dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.3 - '@eslint/js': 9.39.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.39.1 '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 @@ -8047,6 +8099,8 @@ snapshots: esutils@2.0.3: {} + eventemitter3@5.0.1: {} + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -8070,16 +8124,28 @@ snapshots: jest-mock: 30.2.0 jest-util: 30.2.0 - fast-copy@4.0.2: {} + fast-copy@3.0.2: {} fast-deep-equal@3.1.3: {} + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} fast-safe-stringify@2.1.1: {} + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + fb-watchman@2.0.2: dependencies: bser: 2.1.1 @@ -8098,18 +8164,9 @@ snapshots: dependencies: flat-cache: 4.0.1 - file-type@21.1.0: + file-type@21.0.0: dependencies: - '@tokenizer/inflate': 0.3.1 - strtok3: 10.3.4 - token-types: 6.1.1 - uint8array-extras: 1.5.0 - transitivePeerDependencies: - - supports-color - - file-type@21.1.1: - dependencies: - '@tokenizer/inflate': 0.4.1 + '@tokenizer/inflate': 0.2.7 strtok3: 10.3.4 token-types: 6.1.1 uint8array-extras: 1.5.0 @@ -8138,7 +8195,7 @@ snapshots: dependencies: magic-string: 0.30.21 mlly: 1.8.0 - rollup: 4.53.5 + rollup: 4.53.1 flat-cache@4.0.1: dependencies: @@ -8163,7 +8220,7 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.5: + form-data@4.0.4: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -8241,11 +8298,15 @@ snapshots: transitivePeerDependencies: - supports-color + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - glob@10.5.0: + glob@10.4.5: dependencies: foreground-child: 3.3.1 jackspeak: 3.4.3 @@ -8254,7 +8315,7 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@11.1.0: + glob@11.0.3: dependencies: foreground-child: 3.3.1 jackspeak: 4.1.1 @@ -8263,12 +8324,6 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.1 - glob@13.0.0: - dependencies: - minimatch: 10.1.1 - minipass: 7.1.2 - path-scurry: 2.0.1 - glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -8291,10 +8346,12 @@ snapshots: graceful-fs@4.2.11: {} + graphemer@1.4.0: {} + graphile-config@0.0.1-beta.18: dependencies: - '@types/interpret': 1.1.4 - '@types/node': 22.19.3 + '@types/interpret': 1.1.3 + '@types/node': 22.19.0 '@types/semver': 7.7.1 chalk: 4.1.2 debug: 4.4.3 @@ -8309,7 +8366,7 @@ snapshots: dependencies: '@graphile/logger': 0.2.0 '@types/debug': 4.1.12 - '@types/pg': 8.16.0 + '@types/pg': 8.15.6 cosmiconfig: 8.3.6(typescript@5.9.3) graphile-config: 0.0.1-beta.18 json5: 2.2.3 @@ -8321,7 +8378,7 @@ snapshots: - supports-color - typescript - graphql-request@7.4.0(graphql@16.12.0): + graphql-request@7.3.1(graphql@16.12.0): dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.12.0) graphql: 16.12.0 @@ -8353,10 +8410,6 @@ snapshots: dependencies: has-symbols: 1.1.0 - hashery@1.3.0: - dependencies: - hookified: 1.14.0 - hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -8367,7 +8420,7 @@ snapshots: dependencies: react-is: 16.13.1 - hookified@1.14.0: {} + hookified@1.12.2: {} html-escaper@2.0.2: {} @@ -8385,6 +8438,7 @@ snapshots: domhandler: 5.0.3 domutils: 3.2.2 entities: 4.5.0 + optional: true http-proxy-agent@7.0.2: dependencies: @@ -8409,7 +8463,7 @@ snapshots: human-signals@2.1.0: {} - iconv-lite@0.7.1: + iconv-lite@0.7.0: dependencies: safer-buffer: 2.1.2 @@ -8440,9 +8494,9 @@ snapshots: inherits@2.0.4: {} - inquirer@8.2.7(@types/node@24.10.4): + inquirer@8.2.7(@types/node@24.10.0): dependencies: - '@inquirer/external-editor': 1.0.3(@types/node@24.10.4) + '@inquirer/external-editor': 1.0.3(@types/node@24.10.0) ansi-escapes: 4.3.2 chalk: 4.1.2 cli-cursor: 3.1.0 @@ -8671,10 +8725,10 @@ snapshots: '@jest/expect': 30.2.0 '@jest/test-result': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 chalk: 4.1.2 co: 4.6.0 - dedent: 1.7.1(babel-plugin-macros@3.1.0) + dedent: 1.7.0(babel-plugin-macros@3.1.0) is-generator-fn: 2.1.0 jest-each: 30.2.0 jest-matcher-utils: 30.2.0 @@ -8691,15 +8745,15 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)): + jest-cli@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)): dependencies: - '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)) + '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) '@jest/test-result': 30.2.0 '@jest/types': 30.2.0 chalk: 4.1.2 exit-x: 0.2.2 import-local: 3.2.0 - jest-config: 30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)) + jest-config: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) jest-util: 30.2.0 jest-validate: 30.2.0 yargs: 17.7.2 @@ -8710,7 +8764,7 @@ snapshots: - supports-color - ts-node - jest-config@30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)): + jest-config@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)): dependencies: '@babel/core': 7.28.5 '@jest/get-type': 30.1.0 @@ -8721,7 +8775,7 @@ snapshots: chalk: 4.1.2 ci-info: 4.3.1 deepmerge: 4.3.1 - glob: 10.5.0 + glob: 10.4.5 graceful-fs: 4.2.11 jest-circus: 30.2.0(babel-plugin-macros@3.1.0) jest-docblock: 30.2.0 @@ -8737,8 +8791,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 24.10.4 - ts-node: 10.9.2(@types/node@24.10.4)(typescript@5.9.3) + '@types/node': 24.10.0 + ts-node: 10.9.2(@types/node@24.10.0)(typescript@5.9.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -8767,7 +8821,7 @@ snapshots: '@jest/environment': 30.2.0 '@jest/fake-timers': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 jest-mock: 30.2.0 jest-util: 30.2.0 jest-validate: 30.2.0 @@ -8775,7 +8829,7 @@ snapshots: jest-haste-map@30.2.0: dependencies: '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -8821,7 +8875,7 @@ snapshots: jest-mock@30.2.0: dependencies: '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 jest-util: 30.2.0 jest-pnp-resolver@1.2.3(jest-resolve@30.2.0): @@ -8855,7 +8909,7 @@ snapshots: '@jest/test-result': 30.2.0 '@jest/transform': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 chalk: 4.1.2 emittery: 0.13.1 exit-x: 0.2.2 @@ -8884,11 +8938,11 @@ snapshots: '@jest/test-result': 30.2.0 '@jest/transform': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 chalk: 4.1.2 cjs-module-lexer: 2.1.1 collect-v8-coverage: 1.0.3 - glob: 10.5.0 + glob: 10.4.5 graceful-fs: 4.2.11 jest-haste-map: 30.2.0 jest-message-util: 30.2.0 @@ -8931,7 +8985,7 @@ snapshots: jest-util@30.2.0: dependencies: '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 chalk: 4.1.2 ci-info: 4.3.1 graceful-fs: 4.2.11 @@ -8950,7 +9004,7 @@ snapshots: dependencies: '@jest/test-result': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -8959,18 +9013,18 @@ snapshots: jest-worker@30.2.0: dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.0 '@ungap/structured-clone': 1.3.0 jest-util: 30.2.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)): + jest@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)): dependencies: - '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)) + '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) '@jest/types': 30.2.0 import-local: 3.2.0 - jest-cli: 30.2.0(@types/node@24.10.4)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3)) + jest-cli: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8980,18 +9034,18 @@ snapshots: jose@4.15.9: {} - jose@6.1.3: {} + jose@6.1.1: {} joycon@3.1.1: {} js-tokens@4.0.0: {} - js-yaml@3.14.2: + js-yaml@3.14.1: dependencies: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.1.1: + js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -9019,9 +9073,9 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - jsonwebtoken@9.0.3: + jsonwebtoken@9.0.2: dependencies: - jws: 4.0.1 + jws: 3.2.2 lodash.includes: 4.3.0 lodash.isboolean: 3.0.3 lodash.isinteger: 4.0.4 @@ -9032,22 +9086,22 @@ snapshots: ms: 2.1.3 semver: 7.7.3 - jwa@2.0.1: + jwa@1.4.2: dependencies: buffer-equal-constant-time: 1.0.1 ecdsa-sig-formatter: 1.0.11 safe-buffer: 5.2.1 - jws@4.0.1: + jws@3.2.2: dependencies: - jwa: 2.0.1 + jwa: 1.4.2 safe-buffer: 5.2.1 keyv@4.5.4: dependencies: json-buffer: 3.0.1 - keyv@5.5.5: + keyv@5.5.3: dependencies: '@keyv/serialize': 1.1.1 @@ -9064,12 +9118,13 @@ snapshots: lines-and-columns@1.2.4: {} - link-preview-js@3.2.0: + link-preview-js@3.1.0: dependencies: cheerio: 1.0.0-rc.11 url: 0.11.0 + optional: true - load-esm@1.0.3: {} + load-esm@1.0.2: {} load-tsconfig@0.2.5: {} @@ -9101,6 +9156,8 @@ snapshots: lodash.once@4.1.1: {} + lodash.sortby@4.7.0: {} + lodash@4.17.21: {} log-symbols@4.1.0: @@ -9118,7 +9175,7 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.2.4: {} + lru-cache@11.2.2: {} lru-cache@5.1.1: dependencies: @@ -9150,6 +9207,8 @@ snapshots: merge-stream@2.0.0: {} + merge2@1.4.1: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -9208,13 +9267,13 @@ snapshots: duplexer2: 0.1.4 object-assign: 4.1.1 - music-metadata@11.10.3: + music-metadata@11.10.0: dependencies: '@borewit/text-codec': 0.2.0 '@tokenizer/token': 0.3.0 content-type: 1.0.5 debug: 4.4.3 - file-type: 21.1.1 + file-type: 21.0.0 media-typer: 1.1.0 strtok3: 10.3.4 token-types: 6.1.1 @@ -9238,39 +9297,39 @@ snapshots: netmask@2.0.2: {} - next-auth@4.24.13(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + next-auth@4.24.13(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: '@babel/runtime': 7.28.4 '@panva/hkdf': 1.2.1 cookie: 0.7.2 jose: 4.15.9 - next: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + next: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) oauth: 0.9.15 openid-client: 5.7.1 - preact: 10.28.0 - preact-render-to-string: 5.2.6(preact@10.28.0) + preact: 10.27.2 + preact-render-to-string: 5.2.6(preact@10.27.2) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) uuid: 8.3.2 - next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@next/env': 15.5.9 + '@next/env': 15.5.4 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001761 + caniuse-lite: 1.0.30001754 postcss: 8.4.31 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) styled-jsx: 5.1.6(react@19.2.0) optionalDependencies: - '@next/swc-darwin-arm64': 15.5.7 - '@next/swc-darwin-x64': 15.5.7 - '@next/swc-linux-arm64-gnu': 15.5.7 - '@next/swc-linux-arm64-musl': 15.5.7 - '@next/swc-linux-x64-gnu': 15.5.7 - '@next/swc-linux-x64-musl': 15.5.7 - '@next/swc-win32-arm64-msvc': 15.5.7 - '@next/swc-win32-x64-msvc': 15.5.7 + '@next/swc-darwin-arm64': 15.5.4 + '@next/swc-darwin-x64': 15.5.4 + '@next/swc-linux-arm64-gnu': 15.5.4 + '@next/swc-linux-arm64-musl': 15.5.4 + '@next/swc-linux-x64-gnu': 15.5.4 + '@next/swc-linux-x64-musl': 15.5.4 + '@next/swc-win32-arm64-msvc': 15.5.4 + '@next/swc-win32-x64-msvc': 15.5.4 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -9299,8 +9358,9 @@ snapshots: nth-check@2.1.1: dependencies: boolbase: 1.0.0 + optional: true - oauth4webapi@3.8.3: {} + oauth4webapi@3.8.2: {} oauth@0.9.15: {} @@ -9334,14 +9394,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 object.groupby@1.0.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 object.values@1.2.1: dependencies: @@ -9412,6 +9472,13 @@ snapshots: dependencies: p-limit: 3.1.0 + p-queue@9.0.1: + dependencies: + eventemitter3: 5.0.1 + p-timeout: 7.0.1 + + p-timeout@7.0.1: {} + p-try@2.2.0: {} pac-proxy-agent@7.2.0: @@ -9449,10 +9516,12 @@ snapshots: dependencies: domhandler: 5.0.3 parse5: 7.3.0 + optional: true parse5@7.3.0: dependencies: entities: 6.0.1 + optional: true path-exists@4.0.0: {} @@ -9469,10 +9538,10 @@ snapshots: path-scurry@2.0.1: dependencies: - lru-cache: 11.2.4 + lru-cache: 11.2.2 minipass: 7.1.2 - path-to-regexp@8.3.0: {} + path-to-regexp@8.2.0: {} path-type@4.0.0: {} @@ -9495,7 +9564,7 @@ snapshots: dependencies: pg-int8: 1.0.1 postgres-array: 2.0.0 - postgres-bytea: 1.0.1 + postgres-bytea: 1.0.0 postgres-date: 1.0.7 postgres-interval: 1.2.0 @@ -9523,21 +9592,17 @@ snapshots: dependencies: split2: 4.2.0 - pino-abstract-transport@3.0.0: - dependencies: - split2: 4.2.0 - - pino-pretty@13.1.3: + pino-pretty@13.1.2: dependencies: colorette: 2.0.20 dateformat: 4.6.3 - fast-copy: 4.0.2 + fast-copy: 3.0.2 fast-safe-stringify: 2.1.1 help-me: 5.0.0 joycon: 3.1.1 minimist: 1.2.8 on-exit-leak-free: 2.1.2 - pino-abstract-transport: 3.0.0 + pino-abstract-transport: 2.0.0 pump: 3.0.3 secure-json-parse: 4.1.0 sonic-boom: 4.2.0 @@ -9589,12 +9654,12 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-load-config@6.0.1(postcss@8.4.31)(tsx@4.21.0): + postcss-load-config@6.0.1(postcss@8.4.31)(tsx@4.20.6): dependencies: lilconfig: 3.1.3 optionalDependencies: postcss: 8.4.31 - tsx: 4.21.0 + tsx: 4.20.6 postcss@8.4.31: dependencies: @@ -9604,7 +9669,7 @@ snapshots: postgres-array@2.0.0: {} - postgres-bytea@1.0.1: {} + postgres-bytea@1.0.0: {} postgres-date@1.0.7: {} @@ -9612,9 +9677,9 @@ snapshots: dependencies: xtend: 4.0.2 - preact-render-to-string@5.2.6(preact@10.28.0): + preact-render-to-string@5.2.6(preact@10.27.2): dependencies: - preact: 10.28.0 + preact: 10.27.2 pretty-format: 3.8.0 preact-render-to-string@6.5.11(preact@10.24.3): @@ -9623,7 +9688,7 @@ snapshots: preact@10.24.3: {} - preact@10.28.0: {} + preact@10.27.2: {} prelude-ls@1.2.1: {} @@ -9673,7 +9738,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 24.10.4 + '@types/node': 24.10.0 long: 5.3.2 proxy-agent@6.5.0: @@ -9696,15 +9761,16 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 - punycode@1.3.2: {} + punycode@1.3.2: + optional: true punycode@2.3.1: {} pure-rand@7.0.1: {} - qified@0.5.3: + qified@0.5.1: dependencies: - hookified: 1.14.0 + hookified: 1.12.2 qr.js@0.0.0: {} @@ -9712,7 +9778,10 @@ snapshots: dependencies: side-channel: 1.1.0 - querystring@0.2.0: {} + querystring@0.2.0: + optional: true + + queue-microtask@1.2.3: {} quick-format-unescaped@4.0.4: {} @@ -9739,7 +9808,7 @@ snapshots: react-is@18.3.1: {} - react-is@19.2.3: {} + react-is@19.2.0: {} react-polyglot@0.7.2(node-polyglot@2.6.0)(react@19.2.0): dependencies: @@ -9804,7 +9873,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-errors: 1.3.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 @@ -9855,36 +9924,42 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 - rollup@4.53.5: + reusify@1.1.0: {} + + rollup@4.53.1: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.5 - '@rollup/rollup-android-arm64': 4.53.5 - '@rollup/rollup-darwin-arm64': 4.53.5 - '@rollup/rollup-darwin-x64': 4.53.5 - '@rollup/rollup-freebsd-arm64': 4.53.5 - '@rollup/rollup-freebsd-x64': 4.53.5 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.5 - '@rollup/rollup-linux-arm-musleabihf': 4.53.5 - '@rollup/rollup-linux-arm64-gnu': 4.53.5 - '@rollup/rollup-linux-arm64-musl': 4.53.5 - '@rollup/rollup-linux-loong64-gnu': 4.53.5 - '@rollup/rollup-linux-ppc64-gnu': 4.53.5 - '@rollup/rollup-linux-riscv64-gnu': 4.53.5 - '@rollup/rollup-linux-riscv64-musl': 4.53.5 - '@rollup/rollup-linux-s390x-gnu': 4.53.5 - '@rollup/rollup-linux-x64-gnu': 4.53.5 - '@rollup/rollup-linux-x64-musl': 4.53.5 - '@rollup/rollup-openharmony-arm64': 4.53.5 - '@rollup/rollup-win32-arm64-msvc': 4.53.5 - '@rollup/rollup-win32-ia32-msvc': 4.53.5 - '@rollup/rollup-win32-x64-gnu': 4.53.5 - '@rollup/rollup-win32-x64-msvc': 4.53.5 + '@rollup/rollup-android-arm-eabi': 4.53.1 + '@rollup/rollup-android-arm64': 4.53.1 + '@rollup/rollup-darwin-arm64': 4.53.1 + '@rollup/rollup-darwin-x64': 4.53.1 + '@rollup/rollup-freebsd-arm64': 4.53.1 + '@rollup/rollup-freebsd-x64': 4.53.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.1 + '@rollup/rollup-linux-arm-musleabihf': 4.53.1 + '@rollup/rollup-linux-arm64-gnu': 4.53.1 + '@rollup/rollup-linux-arm64-musl': 4.53.1 + '@rollup/rollup-linux-loong64-gnu': 4.53.1 + '@rollup/rollup-linux-ppc64-gnu': 4.53.1 + '@rollup/rollup-linux-riscv64-gnu': 4.53.1 + '@rollup/rollup-linux-riscv64-musl': 4.53.1 + '@rollup/rollup-linux-s390x-gnu': 4.53.1 + '@rollup/rollup-linux-x64-gnu': 4.53.1 + '@rollup/rollup-linux-x64-musl': 4.53.1 + '@rollup/rollup-openharmony-arm64': 4.53.1 + '@rollup/rollup-win32-arm64-msvc': 4.53.1 + '@rollup/rollup-win32-ia32-msvc': 4.53.1 + '@rollup/rollup-win32-x64-gnu': 4.53.1 + '@rollup/rollup-win32-x64-msvc': 4.53.1 fsevents: 2.3.3 run-async@2.4.1: {} + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + rxjs@7.8.2: dependencies: tslib: 2.8.1 @@ -10051,7 +10126,9 @@ snapshots: source-map@0.6.1: {} - source-map@0.7.6: {} + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 split2@4.2.0: {} @@ -10091,7 +10168,7 @@ snapshots: call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.0 es-object-atoms: 1.1.1 has-property-descriptors: 1.0.2 @@ -10149,14 +10226,14 @@ snapshots: stylis@4.2.0: {} - sucrase@3.35.1: + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 + glob: 10.4.5 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 - tinyglobby: 0.2.15 ts-interface-checker: 0.1.13 supports-color@7.2.0: @@ -10219,6 +10296,10 @@ snapshots: tr46@0.0.3: {} + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + tree-kill@1.2.2: {} ts-api-utils@2.1.0(typescript@5.9.3): @@ -10227,14 +10308,14 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@types/node@24.10.4)(typescript@5.9.3): + ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 + '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 24.10.4 + '@types/node': 24.10.0 acorn: 8.15.0 acorn-walk: 8.3.4 arg: 4.1.3 @@ -10254,22 +10335,22 @@ snapshots: tslib@2.8.1: {} - tsup@8.5.1(postcss@8.4.31)(tsx@4.21.0)(typescript@5.9.3): + tsup@8.5.0(postcss@8.4.31)(tsx@4.20.6)(typescript@5.9.3): dependencies: - bundle-require: 5.1.0(esbuild@0.27.2) + bundle-require: 5.1.0(esbuild@0.25.12) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 debug: 4.4.3 - esbuild: 0.27.2 + esbuild: 0.25.12 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.4.31)(tsx@4.21.0) + postcss-load-config: 6.0.1(postcss@8.4.31)(tsx@4.20.6) resolve-from: 5.0.0 - rollup: 4.53.5 - source-map: 0.7.6 - sucrase: 3.35.1 + rollup: 4.53.1 + source-map: 0.8.0-beta.0 + sucrase: 3.35.0 tinyexec: 0.3.2 tinyglobby: 0.2.15 tree-kill: 1.2.2 @@ -10282,46 +10363,46 @@ snapshots: - tsx - yaml - tsx@4.21.0: + tsx@4.20.6: dependencies: - esbuild: 0.27.2 + esbuild: 0.25.12 get-tsconfig: 4.13.0 optionalDependencies: fsevents: 2.3.3 - turbo-darwin-64@2.6.3: + turbo-darwin-64@2.6.0: optional: true - turbo-darwin-arm64@2.6.3: + turbo-darwin-arm64@2.6.0: optional: true - turbo-linux-64@2.6.3: + turbo-linux-64@2.6.0: optional: true - turbo-linux-arm64@2.6.3: + turbo-linux-arm64@2.6.0: optional: true - turbo-windows-64@2.6.3: + turbo-windows-64@2.6.0: optional: true - turbo-windows-arm64@2.6.3: + turbo-windows-arm64@2.6.0: optional: true - turbo@2.6.3: + turbo@2.6.0: optionalDependencies: - turbo-darwin-64: 2.6.3 - turbo-darwin-arm64: 2.6.3 - turbo-linux-64: 2.6.3 - turbo-linux-arm64: 2.6.3 - turbo-windows-64: 2.6.3 - turbo-windows-arm64: 2.6.3 + turbo-darwin-64: 2.6.0 + turbo-darwin-arm64: 2.6.0 + turbo-linux-64: 2.6.0 + turbo-linux-arm64: 2.6.0 + turbo-windows-64: 2.6.0 + turbo-windows-arm64: 2.6.0 - twilio@5.11.1: + twilio@5.10.4: dependencies: axios: 1.13.2 dayjs: 1.11.19 https-proxy-agent: 5.0.1 - jsonwebtoken: 9.0.3 + jsonwebtoken: 9.0.2 qs: 6.14.0 scmp: 2.1.0 xmlbuilder: 13.0.2 @@ -10395,7 +10476,7 @@ snapshots: universal-cookie@8.0.1: dependencies: - cookie: 1.1.1 + cookie: 1.0.2 universalify@2.0.1: {} @@ -10423,9 +10504,9 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - update-browserslist-db@1.2.3(browserslist@4.28.1): + update-browserslist-db@1.1.4(browserslist@4.27.0): dependencies: - browserslist: 4.28.1 + browserslist: 4.27.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -10437,6 +10518,7 @@ snapshots: dependencies: punycode: 1.3.2 querystring: 0.2.0 + optional: true use-sync-external-store@1.6.0(react@19.2.0): dependencies: @@ -10468,11 +10550,19 @@ snapshots: webidl-conversions@3.0.1: {} + webidl-conversions@4.0.2: {} + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 From e202eeb9d2ba887146c515fc366942b1763ab8f9 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Tue, 2 Dec 2025 18:00:25 +0100 Subject: [PATCH 08/38] Remove deprecated property --- apps/bridge-whatsapp/src/service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/bridge-whatsapp/src/service.ts b/apps/bridge-whatsapp/src/service.ts index 32701f7..c8938bd 100644 --- a/apps/bridge-whatsapp/src/service.ts +++ b/apps/bridge-whatsapp/src/service.ts @@ -168,7 +168,6 @@ export default class WhatsappService extends Service { await this.createConnection(botID, this.server, { browser: WhatsappService.browserDescription, - printQRInTerminal: true, version, }); } From 57f3ccbaeb27aa6bba99b757bbcafd29a72cb041 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Tue, 2 Dec 2025 18:19:14 +0100 Subject: [PATCH 09/38] Fetch message history at startup --- apps/bridge-whatsapp/src/service.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/bridge-whatsapp/src/service.ts b/apps/bridge-whatsapp/src/service.ts index c8938bd..41450cc 100644 --- a/apps/bridge-whatsapp/src/service.ts +++ b/apps/bridge-whatsapp/src/service.ts @@ -98,6 +98,7 @@ export default class WhatsappService extends Service { ...options, auth: state, generateHighQualityLinkPreview: false, + syncFullHistory: true, msgRetryCounterMap, shouldIgnoreJid: (jid) => isJidBroadcast(jid) || isJidStatusBroadcast(jid), }); @@ -148,6 +149,17 @@ export default class WhatsappService extends Service { await this.queueUnreadMessages(botID, messages); } } + + if (events["messaging-history.set"]) { + const { messages, isLatest } = events["messaging-history.set"]; + logger.info( + { messageCount: messages.length, isLatest }, + "received message history on connection", + ); + if (messages.length > 0) { + await this.queueUnreadMessages(botID, messages); + } + } }); this.connections[botID] = { socket, msgRetryCounterMap }; From 7a6e7d074890dfa673716a9bcc1475207ffe99cc Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Thu, 4 Dec 2025 12:48:49 +0100 Subject: [PATCH 10/38] Update docker.js --- docker/scripts/docker.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/scripts/docker.js b/docker/scripts/docker.js index 3d6e278..5f3e090 100644 --- a/docker/scripts/docker.js +++ b/docker/scripts/docker.js @@ -5,13 +5,13 @@ const app = process.argv[2]; const command = process.argv[3]; const files = { - all: ["zammad", "postgresql", "bridge", "opensearch", "link", "signal-cli-rest-api"], + all: ["zammad", "postgresql", "bridge", "opensearch", "link", "signal-cli-rest-api", "bridge-whatsapp"], linkDev: ["zammad", "postgresql", "opensearch"], link: ["zammad", "postgresql", "opensearch", "link"], linkOnly: ["link"], opensearch: ["opensearch"], - bridgeDev: ["zammad", "postgresql", "signal-cli-rest-api"], - bridge: ["zammad", "postgresql", "bridge", "signal-cli-rest-api"], + bridgeDev: ["zammad", "postgresql", "signal-cli-rest-api", "bridge-whatsapp"], + bridge: ["zammad", "postgresql", "bridge", "signal-cli-rest-api", "bridge-whatsapp"], zammad: ["zammad", "postgresql", "opensearch"], }; @@ -21,7 +21,7 @@ const finalFiles = files[app] .map((file) => ['-f', `docker/compose/${file}.yml`]).flat(); // Add bridge-dev.yml for dev commands that include zammad -const devAppsWithZammad = ['linkDev', 'bridgeDev', 'all']; +const devAppsWithZammad = ['linkDev', 'bridgeDev']; if (devAppsWithZammad.includes(app) && files[app].includes('zammad')) { finalFiles.push('-f', 'docker-compose.bridge-dev.yml'); } From d6dab5fb1f6c1eace8cbc162fed347cd047bfe67 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 17 Dec 2025 22:37:54 +0100 Subject: [PATCH 11/38] Build updates --- docker/buildx/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/buildx/Dockerfile b/docker/buildx/Dockerfile index dc394b5..28679d2 100644 --- a/docker/buildx/Dockerfile +++ b/docker/buildx/Dockerfile @@ -15,7 +15,7 @@ COPY --from=node /usr/local/lib /usr/local/lib COPY --from=node /usr/local/include /usr/local/include COPY --from=node /usr/local/bin /usr/local/bin -# Prepare pnpm (corepack is already enabled in node:22-alpine) +# Prepare pnpm (corepack symlinks already copied from node image) RUN corepack prepare pnpm@9.15.4 --activate # Set up pnpm home From 8688efc5af84b40a434e8cb667eeb1e177a1bee7 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 14 Jan 2026 11:02:11 +0100 Subject: [PATCH 12/38] Regenerate pnpm-lock.yaml after rebase --- pnpm-lock.yaml | 146 ++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 81 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c415592..16f247c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,16 +65,16 @@ importers: version: 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/material-nextjs': specifier: ^6 - version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) + version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) '@mui/x-license': specifier: ^7 version: 7.29.1(@types/react@19.2.2)(react@19.2.0) next: - specifier: 15.5.4 - version: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 15.5.9 + version: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) next-auth: specifier: ^4.24.11 - version: 4.24.13(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 4.24.13(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: 19.2.0 version: 19.2.0 @@ -167,6 +167,9 @@ importers: hapi-pino: specifier: ^13.0.0 version: 13.0.0 + link-preview-js: + specifier: ^3.1.0 + version: 3.1.0 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -267,7 +270,7 @@ importers: version: 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/material-nextjs': specifier: ^6 - version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) + version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) '@mui/x-data-grid-pro': specifier: ^7 version: 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -293,11 +296,11 @@ importers: specifier: ^6.0.0 version: 6.0.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/icons-material@6.5.0(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) next: - specifier: 15.5.4 - version: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 15.5.9 + version: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) next-auth: specifier: ^4.24.11 - version: 4.24.13(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 4.24.13(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: 19.2.0 version: 19.2.0 @@ -376,8 +379,8 @@ importers: specifier: 0.27.5 version: 0.27.5 next: - specifier: 15.5.4 - version: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 15.5.9 + version: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: 19.2.0 version: 19.2.0 @@ -522,8 +525,8 @@ importers: specifier: ^7 version: 7.29.1(@types/react@19.2.2)(react@19.2.0) next: - specifier: 15.5.4 - version: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 15.5.9 + version: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: specifier: 19.2.0 version: 19.2.0 @@ -1802,53 +1805,53 @@ packages: '@nestjs/websockets': optional: true - '@next/env@15.5.4': - resolution: {integrity: sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==} + '@next/env@15.5.9': + resolution: {integrity: sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==} - '@next/swc-darwin-arm64@15.5.4': - resolution: {integrity: sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==} + '@next/swc-darwin-arm64@15.5.7': + resolution: {integrity: sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.5.4': - resolution: {integrity: sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==} + '@next/swc-darwin-x64@15.5.7': + resolution: {integrity: sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.5.4': - resolution: {integrity: sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==} + '@next/swc-linux-arm64-gnu@15.5.7': + resolution: {integrity: sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.5.4': - resolution: {integrity: sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==} + '@next/swc-linux-arm64-musl@15.5.7': + resolution: {integrity: sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.5.4': - resolution: {integrity: sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==} + '@next/swc-linux-x64-gnu@15.5.7': + resolution: {integrity: sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.5.4': - resolution: {integrity: sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==} + '@next/swc-linux-x64-musl@15.5.7': + resolution: {integrity: sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.5.4': - resolution: {integrity: sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==} + '@next/swc-win32-arm64-msvc@15.5.7': + resolution: {integrity: sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.5.4': - resolution: {integrity: sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==} + '@next/swc-win32-x64-msvc@15.5.7': + resolution: {integrity: sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -4145,8 +4148,8 @@ packages: nodemailer: optional: true - next@15.5.4: - resolution: {integrity: sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==} + next@15.5.9: + resolution: {integrity: sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -6394,11 +6397,11 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - '@mui/material-nextjs@6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)': + '@mui/material-nextjs@6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/react': 11.14.0(@types/react@19.2.2)(react@19.2.0) - next: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + next: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 optionalDependencies: '@emotion/cache': 11.14.0 @@ -6635,30 +6638,30 @@ snapshots: tslib: 2.8.1 uid: 2.0.2 - '@next/env@15.5.4': {} + '@next/env@15.5.9': {} - '@next/swc-darwin-arm64@15.5.4': + '@next/swc-darwin-arm64@15.5.7': optional: true - '@next/swc-darwin-x64@15.5.4': + '@next/swc-darwin-x64@15.5.7': optional: true - '@next/swc-linux-arm64-gnu@15.5.4': + '@next/swc-linux-arm64-gnu@15.5.7': optional: true - '@next/swc-linux-arm64-musl@15.5.4': + '@next/swc-linux-arm64-musl@15.5.7': optional: true - '@next/swc-linux-x64-gnu@15.5.4': + '@next/swc-linux-x64-gnu@15.5.7': optional: true - '@next/swc-linux-x64-musl@15.5.4': + '@next/swc-linux-x64-musl@15.5.7': optional: true - '@next/swc-win32-arm64-msvc@15.5.4': + '@next/swc-win32-arm64-msvc@15.5.7': optional: true - '@next/swc-win32-x64-msvc@15.5.4': + '@next/swc-win32-x64-msvc@15.5.7': optional: true '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': @@ -7364,8 +7367,7 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - boolbase@1.0.0: - optional: true + boolbase@1.0.0: {} brace-expansion@1.1.12: dependencies: @@ -7465,7 +7467,6 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 domutils: 3.2.2 - optional: true cheerio@1.0.0-rc.11: dependencies: @@ -7477,7 +7478,6 @@ snapshots: parse5: 7.3.0 parse5-htmlparser2-tree-adapter: 7.1.0 tslib: 2.8.1 - optional: true chokidar@4.0.3: dependencies: @@ -7608,10 +7608,8 @@ snapshots: domhandler: 5.0.3 domutils: 3.2.2 nth-check: 2.1.1 - optional: true - css-what@6.2.2: - optional: true + css-what@6.2.2: {} csstype@3.1.3: {} @@ -7705,22 +7703,18 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 entities: 4.5.0 - optional: true - domelementtype@2.3.0: - optional: true + domelementtype@2.3.0: {} domhandler@5.0.3: dependencies: domelementtype: 2.3.0 - optional: true domutils@3.2.2: dependencies: dom-serializer: 2.0.0 domelementtype: 2.3.0 domhandler: 5.0.3 - optional: true dotenv-cli@10.0.0: dependencies: @@ -7780,11 +7774,9 @@ snapshots: dependencies: once: 1.4.0 - entities@4.5.0: - optional: true + entities@4.5.0: {} - entities@6.0.1: - optional: true + entities@6.0.1: {} error-ex@1.3.4: dependencies: @@ -8438,7 +8430,6 @@ snapshots: domhandler: 5.0.3 domutils: 3.2.2 entities: 4.5.0 - optional: true http-proxy-agent@7.0.2: dependencies: @@ -9122,7 +9113,6 @@ snapshots: dependencies: cheerio: 1.0.0-rc.11 url: 0.11.0 - optional: true load-esm@1.0.2: {} @@ -9297,13 +9287,13 @@ snapshots: netmask@2.0.2: {} - next-auth@4.24.13(next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + next-auth@4.24.13(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: '@babel/runtime': 7.28.4 '@panva/hkdf': 1.2.1 cookie: 0.7.2 jose: 4.15.9 - next: 15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + next: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) oauth: 0.9.15 openid-client: 5.7.1 preact: 10.27.2 @@ -9312,9 +9302,9 @@ snapshots: react-dom: 19.2.0(react@19.2.0) uuid: 8.3.2 - next@15.5.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@next/env': 15.5.4 + '@next/env': 15.5.9 '@swc/helpers': 0.5.15 caniuse-lite: 1.0.30001754 postcss: 8.4.31 @@ -9322,14 +9312,14 @@ snapshots: react-dom: 19.2.0(react@19.2.0) styled-jsx: 5.1.6(react@19.2.0) optionalDependencies: - '@next/swc-darwin-arm64': 15.5.4 - '@next/swc-darwin-x64': 15.5.4 - '@next/swc-linux-arm64-gnu': 15.5.4 - '@next/swc-linux-arm64-musl': 15.5.4 - '@next/swc-linux-x64-gnu': 15.5.4 - '@next/swc-linux-x64-musl': 15.5.4 - '@next/swc-win32-arm64-msvc': 15.5.4 - '@next/swc-win32-x64-msvc': 15.5.4 + '@next/swc-darwin-arm64': 15.5.7 + '@next/swc-darwin-x64': 15.5.7 + '@next/swc-linux-arm64-gnu': 15.5.7 + '@next/swc-linux-arm64-musl': 15.5.7 + '@next/swc-linux-x64-gnu': 15.5.7 + '@next/swc-linux-x64-musl': 15.5.7 + '@next/swc-win32-arm64-msvc': 15.5.7 + '@next/swc-win32-x64-msvc': 15.5.7 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -9358,7 +9348,6 @@ snapshots: nth-check@2.1.1: dependencies: boolbase: 1.0.0 - optional: true oauth4webapi@3.8.2: {} @@ -9516,12 +9505,10 @@ snapshots: dependencies: domhandler: 5.0.3 parse5: 7.3.0 - optional: true parse5@7.3.0: dependencies: entities: 6.0.1 - optional: true path-exists@4.0.0: {} @@ -9761,8 +9748,7 @@ snapshots: end-of-stream: 1.4.5 once: 1.4.0 - punycode@1.3.2: - optional: true + punycode@1.3.2: {} punycode@2.3.1: {} @@ -9778,8 +9764,7 @@ snapshots: dependencies: side-channel: 1.1.0 - querystring@0.2.0: - optional: true + querystring@0.2.0: {} queue-microtask@1.2.3: {} @@ -10518,7 +10503,6 @@ snapshots: dependencies: punycode: 1.3.2 querystring: 0.2.0 - optional: true use-sync-external-store@1.6.0(react@19.2.0): dependencies: From 57d71734852f2e4d805a5b96d412d36c74930881 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 14 Jan 2026 11:33:11 +0100 Subject: [PATCH 13/38] Bump version to 3.4.0-beta.4 --- apps/bridge-frontend/package.json | 2 +- apps/bridge-migrations/package.json | 2 +- apps/bridge-whatsapp/package.json | 2 +- apps/bridge-worker/package.json | 2 +- apps/link/package.json | 2 +- package.json | 2 +- packages/bridge-common/package.json | 2 +- packages/bridge-ui/package.json | 2 +- packages/eslint-config/package.json | 2 +- packages/jest-config/package.json | 2 +- packages/logger/package.json | 2 +- packages/signal-api/package.json | 2 +- packages/typescript-config/package.json | 2 +- packages/ui/package.json | 2 +- packages/zammad-addon-bridge/package.json | 2 +- packages/zammad-addon-common/package.json | 2 +- packages/zammad-addon-hardening/package.json | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/bridge-frontend/package.json b/apps/bridge-frontend/package.json index 028641a..10bc76c 100644 --- a/apps/bridge-frontend/package.json +++ b/apps/bridge-frontend/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-frontend", - "version": "3.3.5", + "version": "3.4.0-beta.4", "type": "module", "scripts": { "dev": "next dev", diff --git a/apps/bridge-migrations/package.json b/apps/bridge-migrations/package.json index b6740ce..336547f 100644 --- a/apps/bridge-migrations/package.json +++ b/apps/bridge-migrations/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-migrations", - "version": "3.3.5", + "version": "3.4.0-beta.4", "type": "module", "scripts": { "migrate:up:all": "tsx migrate.ts up:all", diff --git a/apps/bridge-whatsapp/package.json b/apps/bridge-whatsapp/package.json index 5d4ad9e..85edf0b 100644 --- a/apps/bridge-whatsapp/package.json +++ b/apps/bridge-whatsapp/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-whatsapp", - "version": "3.3.5", + "version": "3.4.0-beta.4", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/bridge-worker/package.json b/apps/bridge-worker/package.json index 670d742..a196d32 100644 --- a/apps/bridge-worker/package.json +++ b/apps/bridge-worker/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-worker", - "version": "3.3.5", + "version": "3.4.0-beta.4", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/link/package.json b/apps/link/package.json index 1f15196..d238ece 100644 --- a/apps/link/package.json +++ b/apps/link/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/link", - "version": "3.3.5", + "version": "3.4.0-beta.4", "type": "module", "scripts": { "dev": "next dev -H 0.0.0.0", diff --git a/package.json b/package.json index df74908..1062fa3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "Link from the Center for Digital Resilience", "scripts": { "dev": "dotenv -- turbo dev", diff --git a/packages/bridge-common/package.json b/packages/bridge-common/package.json index 91b9696..ecf5e8c 100644 --- a/packages/bridge-common/package.json +++ b/packages/bridge-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-common", - "version": "3.3.5", + "version": "3.4.0-beta.4", "main": "build/main/index.js", "type": "module", "author": "Darren Clarke ", diff --git a/packages/bridge-ui/package.json b/packages/bridge-ui/package.json index 2e4d6fa..8ef50ca 100644 --- a/packages/bridge-ui/package.json +++ b/packages/bridge-ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-ui", - "version": "3.3.5", + "version": "3.4.0-beta.4", "scripts": { "build": "tsc -p tsconfig.json" }, diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index c579d56..85b137e 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/eslint-config", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "amigo's eslint config", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index 591a33a..938525a 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/jest-config", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/logger/package.json b/packages/logger/package.json index cda0e71..a0fa4fb 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/logger", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "Shared logging utility for Link Stack monorepo", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/packages/signal-api/package.json b/packages/signal-api/package.json index 0905a16..67a0cc1 100644 --- a/packages/signal-api/package.json +++ b/packages/signal-api/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/signal-api", - "version": "3.3.5", + "version": "3.4.0-beta.4", "type": "module", "main": "build/index.js", "exports": { diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 98021b8..4d91682 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/typescript-config", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "Shared TypeScript config", "license": "AGPL-3.0-or-later", "author": "Abel Luck ", diff --git a/packages/ui/package.json b/packages/ui/package.json index a12655e..599609b 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/ui", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "", "scripts": { "build": "tsc -p tsconfig.json" diff --git a/packages/zammad-addon-bridge/package.json b/packages/zammad-addon-bridge/package.json index a7ef115..57dedaa 100644 --- a/packages/zammad-addon-bridge/package.json +++ b/packages/zammad-addon-bridge/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-bridge", "displayName": "Bridge", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "An addon that adds CDR Bridge channels to Zammad.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", diff --git a/packages/zammad-addon-common/package.json b/packages/zammad-addon-common/package.json index 2b3c510..4e769b5 100644 --- a/packages/zammad-addon-common/package.json +++ b/packages/zammad-addon-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/zammad-addon-common", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "", "bin": { "zpm-build": "./dist/build.js", diff --git a/packages/zammad-addon-hardening/package.json b/packages/zammad-addon-hardening/package.json index 725472b..53ee291 100644 --- a/packages/zammad-addon-hardening/package.json +++ b/packages/zammad-addon-hardening/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-hardening", "displayName": "Hardening", - "version": "3.3.5", + "version": "3.4.0-beta.4", "description": "A Zammad addon that hardens a Zammad instance according to CDR's needs.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", From 2db6bc5047ba68be311189a1f18128a16eb6b69e Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Thu, 15 Jan 2026 10:01:15 +0100 Subject: [PATCH 14/38] Fix: Use senderPn for phone number instead of LID from remoteJid Baileys 7 uses LIDs (Linked IDs) in remoteJid for some messages instead of phone numbers. This caused messages to be matched to wrong tickets because the LID was used as the sender identifier instead of the actual phone number. Now we: - Extract senderPn/participantPn from message key (Baileys 7 fields) - Prefer these phone number fields over remoteJid - Skip messages if we can't determine the phone number (LID with no phone) --- apps/bridge-whatsapp/src/service.ts | 38 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/apps/bridge-whatsapp/src/service.ts b/apps/bridge-whatsapp/src/service.ts index 69a1895..6b32600 100644 --- a/apps/bridge-whatsapp/src/service.ts +++ b/apps/bridge-whatsapp/src/service.ts @@ -175,18 +175,20 @@ export default class WhatsappService extends Service { } private async queueMessage(botID: string, webMessageInfo: proto.IWebMessageInfo) { - const { - key: { id, fromMe, remoteJid }, - message, - messageTimestamp, - } = webMessageInfo; - logger.info("Message type debug"); - for (const key in message) { - logger.info( - { key, exists: !!message[key as keyof proto.IMessage] }, - "Message field", - ); + const { key, message, messageTimestamp } = webMessageInfo; + if (!key) { + logger.warn("Message missing key, skipping"); + return; } + const { id, fromMe, remoteJid } = key; + // Baileys 7 uses LIDs (Linked IDs) instead of phone numbers in some cases. + // senderPn contains the actual phone number when available. + const senderPn = (key as any).senderPn as string | undefined; + const participantPn = (key as any).participantPn as string | undefined; + logger.info( + { remoteJid, senderPn, participantPn, fromMe }, + "Processing incoming message", + ); const isValidMessage = message && remoteJid !== "status@broadcast" && !fromMe; if (isValidMessage) { const { audioMessage, documentMessage, imageMessage, videoMessage } = message; @@ -244,9 +246,21 @@ export default class WhatsappService extends Service { videoMessage, ].find((text) => text && text !== ""); + // Prefer phone number fields (senderPn/participantPn) over remoteJid + // remoteJid may contain LIDs which are not phone numbers + const phoneFromJid = remoteJid?.split("@")[0]; + const isLidJid = remoteJid?.endsWith("@lid"); + // Use senderPn/participantPn if available, otherwise use remoteJid only if it's not a LID + const senderPhone = senderPn?.split("@")[0] || participantPn?.split("@")[0] || (!isLidJid ? phoneFromJid : undefined); + + if (!senderPhone) { + logger.warn({ remoteJid, senderPn, participantPn }, "Could not determine sender phone number, skipping message"); + return; + } + const payload = { to: botID, - from: remoteJid?.split("@")[0], + from: senderPhone, messageId: id, sentAt: new Date((messageTimestamp as number) * 1000).toISOString(), message: messageText, From 3d8f794cabf1c02676b52d272a05f709b37b953c Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Thu, 15 Jan 2026 10:01:15 +0100 Subject: [PATCH 15/38] Add user ID support for Baileys 7 LIDs and Signal UUIDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Baileys 7 uses LIDs (Linked IDs) instead of phone numbers in remoteJid for some messages. This caused messages to be matched to wrong tickets because the LID was used as the sender identifier. This commit adds proper support for both phone numbers and user IDs across WhatsApp and Signal channels. Changes: Database: - Add migration for whatsapp_user_id and signal_user_id fields on users table Zammad controllers: - Update user lookup with 3-step fallback: phone → dedicated user_id field → user_id in phone field (legacy) - Store user IDs in dedicated fields when available - Update phone field when we receive actual phone number for legacy records - Fix redundant condition in Signal controller Bridge services: - Extract both phone (from senderPn/participantPn) and LID (from remoteJid) - Send both identifiers to Zammad via webhooks - Use camelCase (userId) in bridge-whatsapp, convert to snake_case (user_id) in bridge-worker for Zammad compatibility Baileys 7 compliance: - Remove broken loadAllUnreadMessages() call (removed in Baileys 7) - Return descriptive error directing users to use webhooks instead Misc: - Add docs/ to .gitignore --- .gitignore | 1 + apps/bridge-whatsapp/src/service.ts | 50 ++++++++++++----- .../tasks/fetch-signal-messages.ts | 1 + .../tasks/signal/receive-signal-message.ts | 3 ++ .../whatsapp/receive-whatsapp-message.ts | 5 +- .../channels_cdr_signal_controller.rb | 52 +++++++++++++----- .../channels_cdr_whatsapp_controller.rb | 53 +++++++++++++++---- .../20260115000001_add_messaging_user_ids.rb | 25 +++++++++ 8 files changed, 154 insertions(+), 36 deletions(-) create mode 100644 packages/zammad-addon-bridge/src/db/addon/bridge/20260115000001_add_messaging_user_ids.rb diff --git a/.gitignore b/.gitignore index 4011990..9b270af 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ project.org apps/bridge-worker/scripts/* ENVIRONMENT_VARIABLES_MIGRATION.md local-scripts/* +docs/ diff --git a/apps/bridge-whatsapp/src/service.ts b/apps/bridge-whatsapp/src/service.ts index 41450cc..43bc205 100644 --- a/apps/bridge-whatsapp/src/service.ts +++ b/apps/bridge-whatsapp/src/service.ts @@ -193,13 +193,14 @@ export default class WhatsappService extends Service { return; } const { id, fromMe, remoteJid } = key; - logger.info("Message type debug"); - for (const key in message) { - logger.info( - { key, exists: !!message[key as keyof proto.IMessage] }, - "Message field", - ); - } + // Baileys 7 uses LIDs (Linked IDs) instead of phone numbers in some cases. + // senderPn contains the actual phone number when available. + const senderPn = (key as any).senderPn as string | undefined; + const participantPn = (key as any).participantPn as string | undefined; + logger.info( + { remoteJid, senderPn, participantPn, fromMe }, + "Processing incoming message", + ); const isValidMessage = message && remoteJid !== "status@broadcast" && !fromMe; if (isValidMessage) { const { audioMessage, documentMessage, imageMessage, videoMessage } = message; @@ -257,9 +258,27 @@ export default class WhatsappService extends Service { videoMessage, ].find((text) => text && text !== ""); + // Extract phone number and user ID (LID) separately + // remoteJid may contain LIDs (Baileys 7+) which are not phone numbers + const jidValue = remoteJid?.split("@")[0]; + const isLidJid = remoteJid?.endsWith("@lid"); + + // Phone number: prefer senderPn/participantPn, fall back to remoteJid only if it's not a LID + const senderPhone = senderPn?.split("@")[0] || participantPn?.split("@")[0] || (!isLidJid ? jidValue : undefined); + + // User ID (LID): extract from remoteJid if it's a LID format + const senderUserId = isLidJid ? jidValue : undefined; + + // Must have at least one identifier + if (!senderPhone && !senderUserId) { + logger.warn({ remoteJid, senderPn, participantPn }, "Could not determine sender identity, skipping message"); + return; + } + const payload = { to: botID, - from: remoteJid?.split("@")[0], + from: senderPhone, + userId: senderUserId, messageId: id, sentAt: new Date((messageTimestamp as number) * 1000).toISOString(), message: messageText, @@ -423,12 +442,17 @@ export default class WhatsappService extends Service { } async receive( - botID: string, + _botID: string, _lastReceivedDate: Date, ): Promise { - const connection = this.connections[botID]?.socket; - const messages = await connection.loadAllUnreadMessages(); - - return messages; + // loadAllUnreadMessages() was removed in Baileys 7.x + // Messages are now delivered via events (messages.upsert, messaging-history.set) + // and forwarded to webhooks automatically. + // See: https://baileys.wiki/docs/migration/to-v7.0.0/ + throw new Error( + "Message polling is no longer supported in Baileys 7.x. " + + "Please configure a webhook to receive messages instead. " + + "Messages are automatically forwarded to BRIDGE_FRONTEND_URL/api/whatsapp/bots/{id}/receive" + ); } } diff --git a/apps/bridge-worker/tasks/fetch-signal-messages.ts b/apps/bridge-worker/tasks/fetch-signal-messages.ts index f4bac04..6769a81 100644 --- a/apps/bridge-worker/tasks/fetch-signal-messages.ts +++ b/apps/bridge-worker/tasks/fetch-signal-messages.ts @@ -168,6 +168,7 @@ const processMessage = async ({ token: id, to: toRecipient, from: source, + userId: sourceUuid, // Signal user UUID for user identification messageId: `${sourceUuid}-${rawTimestamp}`, message: dataMessage?.message, sentAt: timestamp.toISOString(), diff --git a/apps/bridge-worker/tasks/signal/receive-signal-message.ts b/apps/bridge-worker/tasks/signal/receive-signal-message.ts index a504b3c..331f41a 100644 --- a/apps/bridge-worker/tasks/signal/receive-signal-message.ts +++ b/apps/bridge-worker/tasks/signal/receive-signal-message.ts @@ -9,6 +9,7 @@ interface ReceiveSignalMessageTaskOptions { token: string; to: string; from: string; + userId?: string; // Signal user UUID for user identification messageId: string; sentAt: string; message: string; @@ -22,6 +23,7 @@ const receiveSignalMessageTask = async ({ token, to, from, + userId, messageId, sentAt, message, @@ -212,6 +214,7 @@ const receiveSignalMessageTask = async ({ const payload = { to: finalTo, from, + user_id: userId, // Signal user UUID for user identification message_id: messageId, sent_at: sentAt, message, diff --git a/apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts b/apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts index 48adc6f..94cee82 100644 --- a/apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts +++ b/apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts @@ -3,7 +3,8 @@ import { db, getWorkerUtils } from "@link-stack/bridge-common"; interface ReceiveWhatsappMessageTaskOptions { token: string; to: string; - from: string; + from?: string; + userId?: string; messageId: string; sentAt: string; message: string; @@ -16,6 +17,7 @@ const receiveWhatsappMessageTask = async ({ token, to, from, + userId, messageId, sentAt, message, @@ -33,6 +35,7 @@ const receiveWhatsappMessageTask = async ({ const payload = { to, from, + user_id: userId, message_id: messageId, sent_at: sentAt, message, diff --git a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb index f09c458..bd22b09 100644 --- a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb +++ b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb @@ -154,16 +154,31 @@ class ChannelsCdrSignalController < ApplicationController return if Ticket::Article.exists?(message_id: "cdr_signal.#{message_id}") receiver_phone_number = params[:to].strip - sender_phone_number = params[:from].strip + sender_phone_number = params[:from].present? ? params[:from].strip : nil + sender_user_id = params[:user_id].present? ? params[:user_id].strip : nil # Check if this is a group message using the is_group flag from bridge-worker # This flag is set when: # 1. The original message came from a Signal group # 2. Bridge-worker created a new group for the conversation - is_group_message = params[:is_group].to_s == 'true' || params[:is_group].to_s == 'true' + is_group_message = params[:is_group].to_s == 'true' + + # Lookup customer with fallback chain: + # 1. Phone number in phone/mobile fields (preferred) + # 2. Signal user ID in signal_user_id field + # 3. User ID in phone/mobile fields (legacy - we used to store UUIDs there) + customer = nil + if sender_phone_number.present? + customer = User.find_by(phone: sender_phone_number) + customer ||= User.find_by(mobile: sender_phone_number) + end + if customer.nil? && sender_user_id.present? + customer = User.find_by(signal_user_id: sender_user_id) + # Legacy fallback: user ID might be stored in phone field + customer ||= User.find_by(phone: sender_user_id) + customer ||= User.find_by(mobile: sender_user_id) + end - customer = User.find_by(phone: sender_phone_number) - customer ||= User.find_by(mobile: sender_phone_number) unless customer role_ids = Role.signup_role_ids customer = User.create( @@ -171,7 +186,8 @@ class ChannelsCdrSignalController < ApplicationController lastname: '', email: '', password: '', - phone: sender_phone_number, + phone: sender_phone_number.presence || sender_user_id, + signal_user_id: sender_user_id, note: 'CDR Signal', active: true, role_ids: role_ids, @@ -180,6 +196,15 @@ class ChannelsCdrSignalController < ApplicationController ) end + # Update signal_user_id if we have it and customer doesn't + if sender_user_id.present? && customer.signal_user_id.blank? + customer.update(signal_user_id: sender_user_id) + end + # Update phone if we have it and customer only has user_id in phone field + if sender_phone_number.present? && customer.phone == sender_user_id + customer.update(phone: sender_phone_number) + end + # set current user UserInfo.current_user_id = customer.id current_user_set(customer, 'token_auth') @@ -208,7 +233,8 @@ class ChannelsCdrSignalController < ApplicationController attachment_data_base64 = params[:attachment] attachment_filename = params[:filename] attachment_mimetype = params[:mime_type] - title = "Message from #{sender_phone_number} at #{sent_at}" + sender_display = sender_phone_number.presence || sender_user_id + title = "Message from #{sender_display} at #{sent_at}" body = message # find ticket or create one @@ -218,7 +244,7 @@ class ChannelsCdrSignalController < ApplicationController Rails.logger.info "=== SIGNAL GROUP TICKET LOOKUP ===" Rails.logger.info "Looking for ticket with group_id: #{receiver_phone_number}" Rails.logger.info "Customer ID: #{customer.id}" - Rails.logger.info "Customer Phone: #{sender_phone_number}" + Rails.logger.info "Customer Phone: #{sender_display}" Rails.logger.info "Channel ID: #{channel.id}" begin @@ -256,12 +282,13 @@ class ChannelsCdrSignalController < ApplicationController ticket.state = Ticket::State.find_by(default_follow_up: true) if ticket.state_id != new_state.id else # Set up chat_id based on whether this is a group message - chat_id = is_group_message ? receiver_phone_number : sender_phone_number + chat_id = is_group_message ? receiver_phone_number : (sender_phone_number.presence || sender_user_id) # Build preferences with group_id included if needed cdr_signal_prefs = { - bot_token: channel.options[:bot_token], # change to bot id - chat_id: chat_id + bot_token: channel.options[:bot_token], + chat_id: chat_id, + user_id: sender_user_id } Rails.logger.info "=== CREATING NEW TICKET ===" @@ -283,7 +310,7 @@ class ChannelsCdrSignalController < ApplicationController ticket.save! article_params = { - from: sender_phone_number, + from: sender_display, to: receiver_phone_number, sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id, subject: title, @@ -296,7 +323,8 @@ class ChannelsCdrSignalController < ApplicationController cdr_signal: { timestamp: sent_at, message_id: message_id, - from: sender_phone_number + from: sender_phone_number, + user_id: sender_user_id } } } diff --git a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb index c30d5ee..bc91676 100644 --- a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb +++ b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb @@ -123,12 +123,16 @@ class ChannelsCdrWhatsappController < ApplicationController errors = {} %i[to - from message_id sent_at].each do |field| errors[field] = 'required' if params[field].blank? end + # At least one of from (phone) or user_id must be present + if params[:from].blank? && params[:user_id].blank? + errors[:from] = 'required (or user_id)' + end + if errors.present? render json: { errors: errors @@ -141,9 +145,25 @@ class ChannelsCdrWhatsappController < ApplicationController return if Ticket::Article.exists?(message_id: "cdr_whatsapp.#{message_id}") receiver_phone_number = params[:to].strip - sender_phone_number = params[:from].strip - customer = User.find_by(phone: sender_phone_number) - customer ||= User.find_by(mobile: sender_phone_number) + sender_phone_number = params[:from].present? ? params[:from].strip : nil + sender_user_id = params[:user_id].present? ? params[:user_id].strip : nil + + # Lookup customer with fallback chain: + # 1. Phone number in phone/mobile fields (preferred) + # 2. WhatsApp user ID in whatsapp_user_id field + # 3. User ID in phone/mobile fields (legacy - we used to store LIDs there) + customer = nil + if sender_phone_number.present? + customer = User.find_by(phone: sender_phone_number) + customer ||= User.find_by(mobile: sender_phone_number) + end + if customer.nil? && sender_user_id.present? + customer = User.find_by(whatsapp_user_id: sender_user_id) + # Legacy fallback: user ID might be stored in phone field + customer ||= User.find_by(phone: sender_user_id) + customer ||= User.find_by(mobile: sender_user_id) + end + unless customer role_ids = Role.signup_role_ids customer = User.create( @@ -151,7 +171,8 @@ class ChannelsCdrWhatsappController < ApplicationController lastname: '', email: '', password: '', - phone: sender_phone_number, + phone: sender_phone_number.presence || sender_user_id, + whatsapp_user_id: sender_user_id, note: 'CDR Whatsapp', active: true, role_ids: role_ids, @@ -160,6 +181,15 @@ class ChannelsCdrWhatsappController < ApplicationController ) end + # Update whatsapp_user_id if we have it and customer doesn't + if sender_user_id.present? && customer.whatsapp_user_id.blank? + customer.update(whatsapp_user_id: sender_user_id) + end + # Update phone if we have it and customer only has user_id in phone field + if sender_phone_number.present? && customer.phone == sender_user_id + customer.update(phone: sender_phone_number) + end + # set current user UserInfo.current_user_id = customer.id current_user_set(customer, 'token_auth') @@ -188,7 +218,8 @@ class ChannelsCdrWhatsappController < ApplicationController attachment_data_base64 = params[:attachment] attachment_filename = params[:filename] attachment_mimetype = params[:mime_type] - title = "Message from #{sender_phone_number} at #{sent_at}" + sender_display = sender_phone_number.presence || sender_user_id + title = "Message from #{sender_display} at #{sent_at}" body = message # find ticket or create one @@ -207,8 +238,9 @@ class ChannelsCdrWhatsappController < ApplicationController preferences: { channel_id: channel.id, cdr_whatsapp: { - bot_token: channel.options[:bot_token], # change to bot id - chat_id: sender_phone_number + bot_token: channel.options[:bot_token], + chat_id: sender_phone_number.presence || sender_user_id, + user_id: sender_user_id } } ) @@ -217,7 +249,7 @@ class ChannelsCdrWhatsappController < ApplicationController ticket.save! article_params = { - from: sender_phone_number, + from: sender_display, to: receiver_phone_number, sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id, subject: title, @@ -230,7 +262,8 @@ class ChannelsCdrWhatsappController < ApplicationController cdr_whatsapp: { timestamp: sent_at, message_id: message_id, - from: sender_phone_number + from: sender_phone_number, + user_id: sender_user_id } } } diff --git a/packages/zammad-addon-bridge/src/db/addon/bridge/20260115000001_add_messaging_user_ids.rb b/packages/zammad-addon-bridge/src/db/addon/bridge/20260115000001_add_messaging_user_ids.rb new file mode 100644 index 0000000..817f9c2 --- /dev/null +++ b/packages/zammad-addon-bridge/src/db/addon/bridge/20260115000001_add_messaging_user_ids.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class AddMessagingUserIds < ActiveRecord::Migration[5.2] + def self.up + # Add WhatsApp user ID field (LID - Linked ID in Baileys 7+) + unless column_exists?(:users, :whatsapp_user_id) + add_column :users, :whatsapp_user_id, :string, limit: 50 + add_index :users, :whatsapp_user_id + end + + # Add Signal user ID field (UUID) + unless column_exists?(:users, :signal_user_id) + add_column :users, :signal_user_id, :string, limit: 50 + add_index :users, :signal_user_id + end + end + + def self.down + remove_index :users, :whatsapp_user_id if index_exists?(:users, :whatsapp_user_id) + remove_column :users, :whatsapp_user_id if column_exists?(:users, :whatsapp_user_id) + + remove_index :users, :signal_user_id if index_exists?(:users, :signal_user_id) + remove_column :users, :signal_user_id if column_exists?(:users, :signal_user_id) + end +end From 87bb05fdd5e059a9967e67097808dacc98649806 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Thu, 15 Jan 2026 16:51:20 +0100 Subject: [PATCH 16/38] Bump version to 3.4.0-beta.5 --- apps/bridge-frontend/package.json | 2 +- apps/bridge-migrations/package.json | 2 +- apps/bridge-whatsapp/package.json | 2 +- apps/bridge-worker/package.json | 2 +- apps/link/package.json | 2 +- package.json | 2 +- packages/bridge-common/package.json | 2 +- packages/bridge-ui/package.json | 2 +- packages/eslint-config/package.json | 2 +- packages/jest-config/package.json | 2 +- packages/logger/package.json | 2 +- packages/signal-api/package.json | 2 +- packages/typescript-config/package.json | 2 +- packages/ui/package.json | 2 +- packages/zammad-addon-bridge/package.json | 2 +- packages/zammad-addon-common/package.json | 2 +- packages/zammad-addon-hardening/package.json | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/bridge-frontend/package.json b/apps/bridge-frontend/package.json index 10bc76c..9f7f34c 100644 --- a/apps/bridge-frontend/package.json +++ b/apps/bridge-frontend/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-frontend", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "type": "module", "scripts": { "dev": "next dev", diff --git a/apps/bridge-migrations/package.json b/apps/bridge-migrations/package.json index 336547f..4c7a25e 100644 --- a/apps/bridge-migrations/package.json +++ b/apps/bridge-migrations/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-migrations", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "type": "module", "scripts": { "migrate:up:all": "tsx migrate.ts up:all", diff --git a/apps/bridge-whatsapp/package.json b/apps/bridge-whatsapp/package.json index 85edf0b..0aa64e8 100644 --- a/apps/bridge-whatsapp/package.json +++ b/apps/bridge-whatsapp/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-whatsapp", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/bridge-worker/package.json b/apps/bridge-worker/package.json index a196d32..f55f734 100644 --- a/apps/bridge-worker/package.json +++ b/apps/bridge-worker/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-worker", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/link/package.json b/apps/link/package.json index d238ece..c712cac 100644 --- a/apps/link/package.json +++ b/apps/link/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/link", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "type": "module", "scripts": { "dev": "next dev -H 0.0.0.0", diff --git a/package.json b/package.json index 1062fa3..6ef88f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "Link from the Center for Digital Resilience", "scripts": { "dev": "dotenv -- turbo dev", diff --git a/packages/bridge-common/package.json b/packages/bridge-common/package.json index ecf5e8c..ac9fcca 100644 --- a/packages/bridge-common/package.json +++ b/packages/bridge-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-common", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "main": "build/main/index.js", "type": "module", "author": "Darren Clarke ", diff --git a/packages/bridge-ui/package.json b/packages/bridge-ui/package.json index 8ef50ca..019d5cf 100644 --- a/packages/bridge-ui/package.json +++ b/packages/bridge-ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-ui", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "scripts": { "build": "tsc -p tsconfig.json" }, diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 85b137e..fad4ed4 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/eslint-config", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "amigo's eslint config", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index 938525a..f66e6bf 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/jest-config", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/logger/package.json b/packages/logger/package.json index a0fa4fb..835c95d 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/logger", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "Shared logging utility for Link Stack monorepo", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/packages/signal-api/package.json b/packages/signal-api/package.json index 67a0cc1..02f3f8e 100644 --- a/packages/signal-api/package.json +++ b/packages/signal-api/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/signal-api", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "type": "module", "main": "build/index.js", "exports": { diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 4d91682..300f7dc 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/typescript-config", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "Shared TypeScript config", "license": "AGPL-3.0-or-later", "author": "Abel Luck ", diff --git a/packages/ui/package.json b/packages/ui/package.json index 599609b..4b2f24a 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/ui", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "", "scripts": { "build": "tsc -p tsconfig.json" diff --git a/packages/zammad-addon-bridge/package.json b/packages/zammad-addon-bridge/package.json index 57dedaa..e7b33c1 100644 --- a/packages/zammad-addon-bridge/package.json +++ b/packages/zammad-addon-bridge/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-bridge", "displayName": "Bridge", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "An addon that adds CDR Bridge channels to Zammad.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", diff --git a/packages/zammad-addon-common/package.json b/packages/zammad-addon-common/package.json index 4e769b5..281214c 100644 --- a/packages/zammad-addon-common/package.json +++ b/packages/zammad-addon-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/zammad-addon-common", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "", "bin": { "zpm-build": "./dist/build.js", diff --git a/packages/zammad-addon-hardening/package.json b/packages/zammad-addon-hardening/package.json index 53ee291..5404381 100644 --- a/packages/zammad-addon-hardening/package.json +++ b/packages/zammad-addon-hardening/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-hardening", "displayName": "Hardening", - "version": "3.4.0-beta.4", + "version": "3.4.0-beta.5", "description": "A Zammad addon that hardens a Zammad instance according to CDR's needs.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", From ac42d7df785bdcbf777a6dd8ec92669aa06ebce7 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Mon, 19 Jan 2026 16:51:51 +0100 Subject: [PATCH 17/38] Use _uid instead of _id to please Rails --- .gitignore | 1 + apps/bridge-frontend/package.json | 2 +- apps/bridge-migrations/package.json | 2 +- apps/bridge-whatsapp/package.json | 2 +- apps/bridge-worker/package.json | 2 +- .../tasks/signal/send-signal-message.ts | 13 +- apps/link/package.json | 2 +- package.json | 2 +- packages/bridge-common/package.json | 2 +- packages/bridge-ui/package.json | 2 +- packages/eslint-config/package.json | 2 +- packages/jest-config/package.json | 2 +- packages/logger/package.json | 2 +- packages/signal-api/package.json | 2 +- packages/typescript-config/package.json | 2 +- packages/ui/package.json | 2 +- packages/zammad-addon-bridge/package.json | 2 +- .../channels_cdr_signal_controller.rb | 15 ++- .../channels_cdr_whatsapp_controller.rb | 12 +- .../20260115000001_add_messaging_user_ids.rb | 126 ++++++++++++++++-- packages/zammad-addon-common/package.json | 2 +- packages/zammad-addon-hardening/package.json | 2 +- 22 files changed, 151 insertions(+), 50 deletions(-) diff --git a/.gitignore b/.gitignore index 9b270af..1f5a509 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ apps/bridge-worker/scripts/* ENVIRONMENT_VARIABLES_MIGRATION.md local-scripts/* docs/ +packages/zammad-addon-bridge/test/ diff --git a/apps/bridge-frontend/package.json b/apps/bridge-frontend/package.json index 9f7f34c..6065502 100644 --- a/apps/bridge-frontend/package.json +++ b/apps/bridge-frontend/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-frontend", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "type": "module", "scripts": { "dev": "next dev", diff --git a/apps/bridge-migrations/package.json b/apps/bridge-migrations/package.json index 4c7a25e..a868cfb 100644 --- a/apps/bridge-migrations/package.json +++ b/apps/bridge-migrations/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-migrations", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "type": "module", "scripts": { "migrate:up:all": "tsx migrate.ts up:all", diff --git a/apps/bridge-whatsapp/package.json b/apps/bridge-whatsapp/package.json index 0aa64e8..9a2dc3d 100644 --- a/apps/bridge-whatsapp/package.json +++ b/apps/bridge-whatsapp/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-whatsapp", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/bridge-worker/package.json b/apps/bridge-worker/package.json index f55f734..b6f0129 100644 --- a/apps/bridge-worker/package.json +++ b/apps/bridge-worker/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-worker", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/bridge-worker/tasks/signal/send-signal-message.ts b/apps/bridge-worker/tasks/signal/send-signal-message.ts index 3235be2..901a7a1 100644 --- a/apps/bridge-worker/tasks/signal/send-signal-message.ts +++ b/apps/bridge-worker/tasks/signal/send-signal-message.ts @@ -64,13 +64,14 @@ const sendSignalMessageTask = async ({ let groupCreated = false; try { - // Check if 'to' is a group ID (UUID format, group.base64 format, or base64) vs phone number - const isUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test( - to, - ); + // Check if 'to' is a group ID (group.base64 format or base64 internal ID) vs individual recipient + // Signal group IDs are 32 bytes = 44 chars base64 (or 43 without padding) + // Signal user UUIDs (ACIs) are 36 chars with hyphens: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + // Phone numbers start with +, usernames with u:, PNIs with PNI: const isGroupPrefix = to.startsWith("group."); - const isBase64 = /^[A-Za-z0-9+/]+=*$/.test(to) && to.length > 20; // Base64 internal_id - const isGroupId = isUUID || isGroupPrefix || isBase64; + const isBase64GroupId = + /^[A-Za-z0-9+/]+=*$/.test(to) && to.length >= 43 && to.length <= 44; + const isGroupId = isGroupPrefix || isBase64GroupId; const enableAutoGroups = process.env.BRIDGE_SIGNAL_AUTO_GROUPS === "true"; logger.debug( diff --git a/apps/link/package.json b/apps/link/package.json index c712cac..88377dd 100644 --- a/apps/link/package.json +++ b/apps/link/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/link", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "type": "module", "scripts": { "dev": "next dev -H 0.0.0.0", diff --git a/package.json b/package.json index 6ef88f0..1ab613e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "Link from the Center for Digital Resilience", "scripts": { "dev": "dotenv -- turbo dev", diff --git a/packages/bridge-common/package.json b/packages/bridge-common/package.json index ac9fcca..071af5e 100644 --- a/packages/bridge-common/package.json +++ b/packages/bridge-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-common", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "main": "build/main/index.js", "type": "module", "author": "Darren Clarke ", diff --git a/packages/bridge-ui/package.json b/packages/bridge-ui/package.json index 019d5cf..3fba241 100644 --- a/packages/bridge-ui/package.json +++ b/packages/bridge-ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-ui", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "scripts": { "build": "tsc -p tsconfig.json" }, diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index fad4ed4..d8ec904 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/eslint-config", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "amigo's eslint config", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index f66e6bf..86e0db3 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/jest-config", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/logger/package.json b/packages/logger/package.json index 835c95d..fafb1b4 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/logger", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "Shared logging utility for Link Stack monorepo", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/packages/signal-api/package.json b/packages/signal-api/package.json index 02f3f8e..731d965 100644 --- a/packages/signal-api/package.json +++ b/packages/signal-api/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/signal-api", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "type": "module", "main": "build/index.js", "exports": { diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 300f7dc..4c846eb 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/typescript-config", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "Shared TypeScript config", "license": "AGPL-3.0-or-later", "author": "Abel Luck ", diff --git a/packages/ui/package.json b/packages/ui/package.json index 4b2f24a..1e90c0b 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/ui", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "", "scripts": { "build": "tsc -p tsconfig.json" diff --git a/packages/zammad-addon-bridge/package.json b/packages/zammad-addon-bridge/package.json index e7b33c1..2c83e3a 100644 --- a/packages/zammad-addon-bridge/package.json +++ b/packages/zammad-addon-bridge/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-bridge", "displayName": "Bridge", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "An addon that adds CDR Bridge channels to Zammad.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", diff --git a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb index bd22b09..d467a13 100644 --- a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb +++ b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb @@ -165,7 +165,7 @@ class ChannelsCdrSignalController < ApplicationController # Lookup customer with fallback chain: # 1. Phone number in phone/mobile fields (preferred) - # 2. Signal user ID in signal_user_id field + # 2. Signal user ID in signal_uid field # 3. User ID in phone/mobile fields (legacy - we used to store UUIDs there) customer = nil if sender_phone_number.present? @@ -173,7 +173,7 @@ class ChannelsCdrSignalController < ApplicationController customer ||= User.find_by(mobile: sender_phone_number) end if customer.nil? && sender_user_id.present? - customer = User.find_by(signal_user_id: sender_user_id) + customer = User.find_by(signal_uid: sender_user_id) # Legacy fallback: user ID might be stored in phone field customer ||= User.find_by(phone: sender_user_id) customer ||= User.find_by(mobile: sender_user_id) @@ -187,7 +187,7 @@ class ChannelsCdrSignalController < ApplicationController email: '', password: '', phone: sender_phone_number.presence || sender_user_id, - signal_user_id: sender_user_id, + signal_uid: sender_user_id, note: 'CDR Signal', active: true, role_ids: role_ids, @@ -196,9 +196,9 @@ class ChannelsCdrSignalController < ApplicationController ) end - # Update signal_user_id if we have it and customer doesn't - if sender_user_id.present? && customer.signal_user_id.blank? - customer.update(signal_user_id: sender_user_id) + # Update signal_uid if we have it and customer doesn't + if sender_user_id.present? && customer.signal_uid.blank? + customer.update(signal_uid: sender_user_id) end # Update phone if we have it and customer only has user_id in phone field if sender_phone_number.present? && customer.phone == sender_user_id @@ -282,7 +282,8 @@ class ChannelsCdrSignalController < ApplicationController ticket.state = Ticket::State.find_by(default_follow_up: true) if ticket.state_id != new_state.id else # Set up chat_id based on whether this is a group message - chat_id = is_group_message ? receiver_phone_number : (sender_phone_number.presence || sender_user_id) + # For direct messages, prefer UUID (more stable than phone numbers which can change) + chat_id = is_group_message ? receiver_phone_number : (sender_user_id.presence || sender_phone_number) # Build preferences with group_id included if needed cdr_signal_prefs = { diff --git a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb index bc91676..b273533 100644 --- a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb +++ b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_whatsapp_controller.rb @@ -150,7 +150,7 @@ class ChannelsCdrWhatsappController < ApplicationController # Lookup customer with fallback chain: # 1. Phone number in phone/mobile fields (preferred) - # 2. WhatsApp user ID in whatsapp_user_id field + # 2. WhatsApp user ID in whatsapp_uid field # 3. User ID in phone/mobile fields (legacy - we used to store LIDs there) customer = nil if sender_phone_number.present? @@ -158,7 +158,7 @@ class ChannelsCdrWhatsappController < ApplicationController customer ||= User.find_by(mobile: sender_phone_number) end if customer.nil? && sender_user_id.present? - customer = User.find_by(whatsapp_user_id: sender_user_id) + customer = User.find_by(whatsapp_uid: sender_user_id) # Legacy fallback: user ID might be stored in phone field customer ||= User.find_by(phone: sender_user_id) customer ||= User.find_by(mobile: sender_user_id) @@ -172,7 +172,7 @@ class ChannelsCdrWhatsappController < ApplicationController email: '', password: '', phone: sender_phone_number.presence || sender_user_id, - whatsapp_user_id: sender_user_id, + whatsapp_uid: sender_user_id, note: 'CDR Whatsapp', active: true, role_ids: role_ids, @@ -181,9 +181,9 @@ class ChannelsCdrWhatsappController < ApplicationController ) end - # Update whatsapp_user_id if we have it and customer doesn't - if sender_user_id.present? && customer.whatsapp_user_id.blank? - customer.update(whatsapp_user_id: sender_user_id) + # Update whatsapp_uid if we have it and customer doesn't + if sender_user_id.present? && customer.whatsapp_uid.blank? + customer.update(whatsapp_uid: sender_user_id) end # Update phone if we have it and customer only has user_id in phone field if sender_phone_number.present? && customer.phone == sender_user_id diff --git a/packages/zammad-addon-bridge/src/db/addon/bridge/20260115000001_add_messaging_user_ids.rb b/packages/zammad-addon-bridge/src/db/addon/bridge/20260115000001_add_messaging_user_ids.rb index 817f9c2..2e247eb 100644 --- a/packages/zammad-addon-bridge/src/db/addon/bridge/20260115000001_add_messaging_user_ids.rb +++ b/packages/zammad-addon-bridge/src/db/addon/bridge/20260115000001_add_messaging_user_ids.rb @@ -1,25 +1,123 @@ -# frozen_string_literal: true - class AddMessagingUserIds < ActiveRecord::Migration[5.2] def self.up - # Add WhatsApp user ID field (LID - Linked ID in Baileys 7+) - unless column_exists?(:users, :whatsapp_user_id) - add_column :users, :whatsapp_user_id, :string, limit: 50 - add_index :users, :whatsapp_user_id + # Add WhatsApp UID column + unless column_exists?(:users, :whatsapp_uid) + add_column :users, :whatsapp_uid, :string, limit: 50 + add_index :users, :whatsapp_uid end + User.reset_column_information - # Add Signal user ID field (UUID) - unless column_exists?(:users, :signal_user_id) - add_column :users, :signal_user_id, :string, limit: 50 - add_index :users, :signal_user_id + # Add Signal UID column + unless column_exists?(:users, :signal_uid) + add_column :users, :signal_uid, :string, limit: 50 + add_index :users, :signal_uid end + User.reset_column_information + + # Register WhatsApp UID with ObjectManager for UI + # Column name: whatsapp_uid, Display name: "WhatsApp User ID" + ObjectManager::Attribute.add( + force: true, + object: 'User', + name: 'whatsapp_uid', + display: 'WhatsApp User ID', + data_type: 'input', + data_option: { + type: 'text', + maxlength: 50, + null: true, + item_class: 'formGroup--halfSize', + }, + editable: false, + active: true, + screens: { + signup: {}, + invite_agent: {}, + invite_customer: {}, + edit: { + '-all-' => { + null: true, + }, + }, + create: { + '-all-' => { + null: true, + }, + }, + view: { + '-all-' => { + shown: true, + }, + }, + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 710, + created_by_id: 1, + updated_by_id: 1, + ) + + # Register Signal UID with ObjectManager for UI + # Column name: signal_uid, Display name: "Signal User ID" + ObjectManager::Attribute.add( + force: true, + object: 'User', + name: 'signal_uid', + display: 'Signal User ID', + data_type: 'input', + data_option: { + type: 'text', + maxlength: 50, + null: true, + item_class: 'formGroup--halfSize', + }, + editable: false, + active: true, + screens: { + signup: {}, + invite_agent: {}, + invite_customer: {}, + edit: { + '-all-' => { + null: true, + }, + }, + create: { + '-all-' => { + null: true, + }, + }, + view: { + '-all-' => { + shown: true, + }, + }, + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 720, + created_by_id: 1, + updated_by_id: 1, + ) end def self.down - remove_index :users, :whatsapp_user_id if index_exists?(:users, :whatsapp_user_id) - remove_column :users, :whatsapp_user_id if column_exists?(:users, :whatsapp_user_id) + ObjectManager::Attribute.remove( + object: 'User', + name: 'whatsapp_uid', + ) - remove_index :users, :signal_user_id if index_exists?(:users, :signal_user_id) - remove_column :users, :signal_user_id if column_exists?(:users, :signal_user_id) + ObjectManager::Attribute.remove( + object: 'User', + name: 'signal_uid', + ) + + remove_index :users, :whatsapp_uid if index_exists?(:users, :whatsapp_uid) + remove_column :users, :whatsapp_uid if column_exists?(:users, :whatsapp_uid) + + remove_index :users, :signal_uid if index_exists?(:users, :signal_uid) + remove_column :users, :signal_uid if column_exists?(:users, :signal_uid) end end diff --git a/packages/zammad-addon-common/package.json b/packages/zammad-addon-common/package.json index 281214c..f63468d 100644 --- a/packages/zammad-addon-common/package.json +++ b/packages/zammad-addon-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/zammad-addon-common", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "", "bin": { "zpm-build": "./dist/build.js", diff --git a/packages/zammad-addon-hardening/package.json b/packages/zammad-addon-hardening/package.json index 5404381..d5122b8 100644 --- a/packages/zammad-addon-hardening/package.json +++ b/packages/zammad-addon-hardening/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-hardening", "displayName": "Hardening", - "version": "3.4.0-beta.5", + "version": "3.4.0-beta.6", "description": "A Zammad addon that hardens a Zammad instance according to CDR's needs.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", From e8f2cc4c5064fead81150dc0921b8c698ec3592f Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 21 Jan 2026 09:58:05 +0100 Subject: [PATCH 18/38] Add Keycloak as a Link login option --- .../link/app/(login)/login/_components/Login.tsx | 16 ++++++++++++++++ apps/link/app/_lib/authentication.ts | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/apps/link/app/(login)/login/_components/Login.tsx b/apps/link/app/(login)/login/_components/Login.tsx index 3207dfd..0df2147 100644 --- a/apps/link/app/(login)/login/_components/Login.tsx +++ b/apps/link/app/(login)/login/_components/Login.tsx @@ -14,6 +14,7 @@ import { Google as GoogleIcon, Microsoft as MicrosoftIcon, Key as KeyIcon, + VpnKey as KeycloakIcon, } from "@mui/icons-material"; import { signIn, getProviders } from "next-auth/react"; import Image from "next/image"; @@ -200,6 +201,21 @@ export const Login: FC = ({ session, baseURL }) => { )} + {provider === "keycloak" && ( + + + signIn("keycloak", { + callbackUrl, + }) + } + > + + Sign in with Keycloak + + + )} {provider === "credentials" && ( diff --git a/apps/link/app/_lib/authentication.ts b/apps/link/app/_lib/authentication.ts index 6370038..49f2e07 100644 --- a/apps/link/app/_lib/authentication.ts +++ b/apps/link/app/_lib/authentication.ts @@ -11,6 +11,7 @@ import Google from "next-auth/providers/google"; import Credentials from "next-auth/providers/credentials"; import Apple from "next-auth/providers/apple"; import AzureADProvider from "next-auth/providers/azure-ad"; +import Keycloak from "next-auth/providers/keycloak"; import { createLogger } from "@link-stack/logger"; const logger = createLogger('link-authentication'); @@ -101,6 +102,18 @@ if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) { tenantId: process.env.AZURE_AD_TENANT_ID, }), ); +} else if ( + process.env.KEYCLOAK_CLIENT_ID && + process.env.KEYCLOAK_CLIENT_SECRET && + process.env.KEYCLOAK_ISSUER +) { + providers.push( + Keycloak({ + clientId: process.env.KEYCLOAK_CLIENT_ID, + clientSecret: process.env.KEYCLOAK_CLIENT_SECRET, + issuer: process.env.KEYCLOAK_ISSUER, + }), + ); } else { providers.push( Credentials({ From eea56dd50bcd36cd99fa2892384496dc65da79cd Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 21 Jan 2026 10:08:59 +0100 Subject: [PATCH 19/38] Reduce Signal message polling frequency from 15s to 30s --- .../tasks/fetch-signal-messages.ts | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/bridge-worker/tasks/fetch-signal-messages.ts b/apps/bridge-worker/tasks/fetch-signal-messages.ts index 6769a81..af6c80c 100644 --- a/apps/bridge-worker/tasks/fetch-signal-messages.ts +++ b/apps/bridge-worker/tasks/fetch-signal-messages.ts @@ -205,17 +205,16 @@ const fetchSignalMessagesTask = async ({ if (scheduleTasks === "true") { // because cron only has minimum 1 minute resolution - for (const offset of [15000, 30000, 45000]) { - await worker.addJob( - "fetch-signal-messages", - { scheduleTasks: "false" }, - { - maxAttempts: 1, - runAt: new Date(Date.now() + offset), - jobKey: `fetchSignalMessages-${offset}`, - }, - ); - } + // schedule one additional job at 30s to achieve 30-second polling + await worker.addJob( + "fetch-signal-messages", + { scheduleTasks: "false" }, + { + maxAttempts: 1, + runAt: new Date(Date.now() + 30000), + jobKey: "fetchSignalMessages-30000", + }, + ); } const messagesClient = new MessagesApi(config); From 72b52463a29a45d48293fb7538146e4e18aaf480 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 21 Jan 2026 10:10:55 +0100 Subject: [PATCH 20/38] Bump version to 3.4.0-beta.7 --- apps/bridge-frontend/package.json | 2 +- apps/bridge-migrations/package.json | 2 +- apps/bridge-whatsapp/package.json | 2 +- apps/bridge-worker/package.json | 2 +- apps/link/package.json | 2 +- package.json | 2 +- packages/bridge-common/package.json | 2 +- packages/bridge-ui/package.json | 2 +- packages/eslint-config/package.json | 2 +- packages/jest-config/package.json | 2 +- packages/logger/package.json | 2 +- packages/signal-api/package.json | 2 +- packages/typescript-config/package.json | 2 +- packages/ui/package.json | 2 +- packages/zammad-addon-bridge/package.json | 2 +- packages/zammad-addon-common/package.json | 2 +- packages/zammad-addon-hardening/package.json | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/bridge-frontend/package.json b/apps/bridge-frontend/package.json index 6065502..321878a 100644 --- a/apps/bridge-frontend/package.json +++ b/apps/bridge-frontend/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-frontend", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "type": "module", "scripts": { "dev": "next dev", diff --git a/apps/bridge-migrations/package.json b/apps/bridge-migrations/package.json index a868cfb..4d22e75 100644 --- a/apps/bridge-migrations/package.json +++ b/apps/bridge-migrations/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-migrations", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "type": "module", "scripts": { "migrate:up:all": "tsx migrate.ts up:all", diff --git a/apps/bridge-whatsapp/package.json b/apps/bridge-whatsapp/package.json index 9a2dc3d..eb5f154 100644 --- a/apps/bridge-whatsapp/package.json +++ b/apps/bridge-whatsapp/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-whatsapp", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/bridge-worker/package.json b/apps/bridge-worker/package.json index b6f0129..c420e05 100644 --- a/apps/bridge-worker/package.json +++ b/apps/bridge-worker/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-worker", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "type": "module", "main": "build/main/index.js", "author": "Darren Clarke ", diff --git a/apps/link/package.json b/apps/link/package.json index 88377dd..665e64a 100644 --- a/apps/link/package.json +++ b/apps/link/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/link", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "type": "module", "scripts": { "dev": "next dev -H 0.0.0.0", diff --git a/package.json b/package.json index 1ab613e..d73e939 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "Link from the Center for Digital Resilience", "scripts": { "dev": "dotenv -- turbo dev", diff --git a/packages/bridge-common/package.json b/packages/bridge-common/package.json index 071af5e..f5ba240 100644 --- a/packages/bridge-common/package.json +++ b/packages/bridge-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-common", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "main": "build/main/index.js", "type": "module", "author": "Darren Clarke ", diff --git a/packages/bridge-ui/package.json b/packages/bridge-ui/package.json index 3fba241..b7a00a4 100644 --- a/packages/bridge-ui/package.json +++ b/packages/bridge-ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/bridge-ui", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "scripts": { "build": "tsc -p tsconfig.json" }, diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index d8ec904..bba55e4 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/eslint-config", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "amigo's eslint config", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index 86e0db3..f143163 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/jest-config", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "", "main": "index.js", "author": "Abel Luck ", diff --git a/packages/logger/package.json b/packages/logger/package.json index fafb1b4..d89a229 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/logger", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "Shared logging utility for Link Stack monorepo", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/packages/signal-api/package.json b/packages/signal-api/package.json index 731d965..d4f84ae 100644 --- a/packages/signal-api/package.json +++ b/packages/signal-api/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/signal-api", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "type": "module", "main": "build/index.js", "exports": { diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 4c846eb..51f201c 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/typescript-config", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "Shared TypeScript config", "license": "AGPL-3.0-or-later", "author": "Abel Luck ", diff --git a/packages/ui/package.json b/packages/ui/package.json index 1e90c0b..e6266c2 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/ui", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "", "scripts": { "build": "tsc -p tsconfig.json" diff --git a/packages/zammad-addon-bridge/package.json b/packages/zammad-addon-bridge/package.json index 2c83e3a..07c5ce6 100644 --- a/packages/zammad-addon-bridge/package.json +++ b/packages/zammad-addon-bridge/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-bridge", "displayName": "Bridge", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "An addon that adds CDR Bridge channels to Zammad.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", diff --git a/packages/zammad-addon-common/package.json b/packages/zammad-addon-common/package.json index f63468d..3229b59 100644 --- a/packages/zammad-addon-common/package.json +++ b/packages/zammad-addon-common/package.json @@ -1,6 +1,6 @@ { "name": "@link-stack/zammad-addon-common", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "", "bin": { "zpm-build": "./dist/build.js", diff --git a/packages/zammad-addon-hardening/package.json b/packages/zammad-addon-hardening/package.json index d5122b8..37a9ead 100644 --- a/packages/zammad-addon-hardening/package.json +++ b/packages/zammad-addon-hardening/package.json @@ -1,7 +1,7 @@ { "name": "@link-stack/zammad-addon-hardening", "displayName": "Hardening", - "version": "3.4.0-beta.6", + "version": "3.4.0-beta.7", "description": "A Zammad addon that hardens a Zammad instance according to CDR's needs.", "scripts": { "build": "node '../zammad-addon-common/dist/build.js'", From b9324cf11c9923c21d875b1137f84844192be925 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 21 Jan 2026 09:44:40 +0100 Subject: [PATCH 21/38] WIP: Add Signal notification support for Zammad agents --- .../_profile/signal_notifications.coffee | 89 +++++++++++ .../profile/signal_notifications.jst.eco | 86 +++++++++++ .../src/app/jobs/signal_notification_job.rb | 63 ++++++++ .../models/transaction/signal_notification.rb | 144 ++++++++++++++++++ .../ticket_create/en.txt.erb | 16 ++ .../ticket_escalation/en.txt.erb | 11 ++ .../ticket_reminder_reached/en.txt.erb | 10 ++ .../ticket_update/en.txt.erb | 14 ++ ...000001_add_signal_notification_settings.rb | 76 +++++++++ .../src/lib/signal_notification_sender.rb | 139 +++++++++++++++++ 10 files changed, 648 insertions(+) create mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/signal_notifications.coffee create mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/signal_notifications.jst.eco create mode 100644 packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb create mode 100644 packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb create mode 100644 packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_create/en.txt.erb create mode 100644 packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_escalation/en.txt.erb create mode 100644 packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_reminder_reached/en.txt.erb create mode 100644 packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_update/en.txt.erb create mode 100644 packages/zammad-addon-bridge/src/db/addon/bridge/20260120000001_add_signal_notification_settings.rb create mode 100644 packages/zammad-addon-bridge/src/lib/signal_notification_sender.rb diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/signal_notifications.coffee b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/signal_notifications.coffee new file mode 100644 index 0000000..23d0df7 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/signal_notifications.coffee @@ -0,0 +1,89 @@ +class ProfileSignalNotifications extends App.ControllerSubContent + @requiredPermission: 'user_preferences.signal_notifications+ticket.agent' + header: __('Signal Notifications') + events: + 'submit form': 'update' + + constructor: -> + super + App.User.full(App.Session.get().id, @render, true, true) + + render: => + config = + enabled: false + events: + create: true + update: true + escalation: true + reminder_reached: true + + user = App.User.find(App.Session.get().id) + user_config = user.preferences?.signal_notifications + if user_config + config = $.extend(true, {}, config, user_config) + + @html App.view('profile/signal_notifications') + config: config + signal_uid: user.signal_uid || '' + signal_notification_enabled: App.Config.get('signal_notification_enabled') + + update: (e) => + e.preventDefault() + params = @formParam(e.target) + + preferences = {} + preferences.signal_notifications = + enabled: params.enabled == 'true' + events: + create: params.event_create == 'true' + update: params.event_update == 'true' + escalation: params.event_escalation == 'true' + reminder_reached: params.event_reminder_reached == 'true' + + @formDisable(e) + + @ajax( + id: 'preferences_signal_notifications' + type: 'PUT' + url: @apiPath + '/users/preferences' + data: JSON.stringify(preferences) + processData: true + success: @successPreferences + error: @error + ) + + if params.signal_uid? + user = App.User.find(App.Session.get().id) + user.signal_uid = params.signal_uid + user.save( + done: => + # User saved successfully + fail: (settings, details) => + @notify( + type: 'error' + msg: details.error || __('Failed to save Signal phone number') + ) + ) + + successPreferences: (data, status, xhr) => + App.User.full( + App.Session.get('id'), + => + App.Event.trigger('ui:rerender') + @notify( + type: 'success' + msg: __('Update successful.') + ) + , + true + ) + + error: (xhr, status, error) => + @render() + data = JSON.parse(xhr.responseText) + @notify( + type: 'error' + msg: data.message + ) + +App.Config.set('SignalNotifications', { prio: 2650, name: __('Signal Notifications'), parent: '#profile', target: '#profile/signal_notifications', permission: ['user_preferences.signal_notifications+ticket.agent'], controller: ProfileSignalNotifications }, 'NavBarProfile') diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/signal_notifications.jst.eco b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/signal_notifications.jst.eco new file mode 100644 index 0000000..4899934 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/signal_notifications.jst.eco @@ -0,0 +1,86 @@ + + +<% if !@signal_notification_enabled: %> + +<% end %> + +
+

<%- @T('Signal Phone Number') %>

+

+ <%- @T('Enter your Signal phone number to receive ticket notifications via Signal.') %> +

+ +
+ + +

<%- @T('Use international format with country code (e.g., +1234567890)') %>

+
+ +

<%- @T('Notification Settings') %>

+ +
+ +
+ +

<%- @T('Notification Events') %>

+

+ <%- @T('Select which events should trigger Signal notifications.') %> +

+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +
diff --git a/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb b/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb new file mode 100644 index 0000000..1da1012 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +class SignalNotificationJob < ApplicationJob + retry_on StandardError, attempts: 3, wait: lambda { |executions| + executions * 60.seconds + } + + def perform(ticket_id:, article_id:, user_id:, type:, changes:) + ticket = Ticket.find_by(id: ticket_id) + return if !ticket + + user = User.find_by(id: user_id) + return if !user + return if user.signal_uid.blank? + + article = article_id ? Ticket::Article.find_by(id: article_id) : nil + + channel = signal_channel + return if !channel + + message = SignalNotificationSender.build_message( + ticket: ticket, + article: article, + user: user, + type: type, + changes: changes + ) + + return if message.blank? + + SignalNotificationSender.send_message( + channel: channel, + recipient: user.signal_uid, + message: message + ) + + add_history(ticket, user, type) + + Rails.logger.info "Sent Signal notification to #{user.signal_uid} for ticket ##{ticket.number} (#{type})" + end + + private + + def signal_channel + channel_id = Setting.get('signal_notification_channel_id') + return unless channel_id + + Channel.find_by(id: channel_id, area: 'Signal::Account', active: true) + end + + def add_history(ticket, user, type) + identifier = user.signal_uid.presence || user.login + recipient_list = "#{identifier}(#{type}:signal)" + + History.add( + o_id: ticket.id, + history_type: 'notification', + history_object: 'Ticket', + value_to: recipient_list, + created_by_id: 1 + ) + end +end diff --git a/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb b/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb new file mode 100644 index 0000000..a7b9f29 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb @@ -0,0 +1,144 @@ +# frozen_string_literal: true + +class Transaction::SignalNotification + include ChecksHumanChanges + + def initialize(item, params = {}) + @item = item + @params = params + end + + def perform + return if Setting.get('import_mode') + return if %w[Ticket Ticket::Article].exclude?(@item[:object]) + return if @params[:disable_notification] + return if !ticket + return if !signal_notifications_enabled? + return if !signal_channel + + collect_signal_recipients.each do |user| + SignalNotificationJob.perform_later( + ticket_id: ticket.id, + article_id: @item[:article_id], + user_id: user.id, + type: @item[:type], + changes: human_changes(@item[:changes], ticket, user) + ) + end + end + + private + + def ticket + @ticket ||= Ticket.find_by(id: @item[:object_id]) + end + + def article + return if !@item[:article_id] + + @article ||= begin + art = Ticket::Article.find_by(id: @item[:article_id]) + return unless art + + sender = Ticket::Article::Sender.lookup(id: art.sender_id) + if sender&.name == 'System' + return if @item[:changes].blank? && art.preferences[:notification] != true + return if art.preferences[:notification] != true + end + + art + end + end + + def current_user + @current_user ||= User.lookup(id: @item[:user_id]) || User.lookup(id: 1) + end + + def signal_notifications_enabled? + Setting.get('signal_notification_enabled') == true + end + + def signal_channel + @signal_channel ||= begin + channel_id = Setting.get('signal_notification_channel_id') + return unless channel_id + + Channel.find_by(id: channel_id, area: 'Signal::Account', active: true) + end + end + + def collect_signal_recipients + recipients = [] + + possible_recipients = possible_recipients_of_group(ticket.group_id) + + mention_users = Mention.where(mentionable_type: @item[:object], mentionable_id: @item[:object_id]).map(&:user) + mention_users.each do |user| + next if !user.group_access?(ticket.group_id, 'read') + + possible_recipients.push(user) + end + + if ticket.owner_id != 1 + possible_recipients.push(ticket.owner) + end + + possible_recipients_with_ooo = Set.new(possible_recipients) + possible_recipients.each do |user| + add_out_of_office_replacement(user, possible_recipients_with_ooo) + end + + possible_recipients_with_ooo.each do |user| + next if recipient_is_current_user?(user) + next if !user.active? + next if !user_has_signal_notifications_enabled?(user) + next if user.signal_uid.blank? + next if !should_notify_for_event?(user) + + recipients.push(user) + end + + recipients.uniq(&:id) + end + + def possible_recipients_of_group(group_id) + Rails.cache.fetch("User/signal_notification/possible_recipients_of_group/#{group_id}/#{User.latest_change}", expires_in: 20.seconds) do + User.group_access(group_id, 'full').sort_by(&:login) + end + end + + def add_out_of_office_replacement(user, recipients) + replacement = user.out_of_office_agent + return unless replacement + return unless TicketPolicy.new(replacement, ticket).agent_read_access? + + recipients.add(replacement) + end + + def recipient_is_current_user?(user) + return false if @params[:interface_handle] != 'application_server' + return true if article&.updated_by_id == user.id + return true if !article && @item[:user_id] == user.id + + false + end + + def user_has_signal_notifications_enabled?(user) + user.preferences.dig('signal_notifications', 'enabled') == true + end + + def should_notify_for_event?(user) + event_type = @item[:type] + return false if event_type.blank? + + event_key = case event_type + when 'create' then 'create' + when 'update', 'update.merged_into', 'update.received_merge', 'update.reaction' then 'update' + when 'reminder_reached' then 'reminder_reached' + when 'escalation', 'escalation_warning' then 'escalation' + else return false + end + + user.preferences.dig('signal_notifications', 'events', event_key) == true + end +end diff --git a/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_create/en.txt.erb b/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_create/en.txt.erb new file mode 100644 index 0000000..9a12210 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_create/en.txt.erb @@ -0,0 +1,16 @@ +[Ticket #<%= ticket.number %>] <%= ticket.title %> + +NEW TICKET + +Group: <%= ticket.group.name %> +Owner: <%= ticket.owner.fullname %> +State: <%= t(ticket.state.name) %> +Priority: <%= t(ticket.priority.name) %> +Customer: <%= ticket.customer.fullname %> +Created by: <%= current_user.fullname %> +<% if article -%> + +<%= article_body_preview(500) %> +<% end -%> + +<%= ticket_url %> diff --git a/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_escalation/en.txt.erb b/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_escalation/en.txt.erb new file mode 100644 index 0000000..a3fdbaa --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_escalation/en.txt.erb @@ -0,0 +1,11 @@ +[Ticket #<%= ticket.number %>] <%= ticket.title %> + +ESCALATION + +Group: <%= ticket.group.name %> +Owner: <%= ticket.owner.fullname %> +State: <%= t(ticket.state.name) %> +Priority: <%= t(ticket.priority.name) %> +Customer: <%= ticket.customer.fullname %> + +<%= ticket_url %> diff --git a/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_reminder_reached/en.txt.erb b/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_reminder_reached/en.txt.erb new file mode 100644 index 0000000..e718346 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_reminder_reached/en.txt.erb @@ -0,0 +1,10 @@ +[Ticket #<%= ticket.number %>] <%= ticket.title %> + +REMINDER REACHED + +Group: <%= ticket.group.name %> +Owner: <%= ticket.owner.fullname %> +State: <%= t(ticket.state.name) %> +Pending till: <%= ticket.pending_time&.strftime('%Y-%m-%d %H:%M') %> + +<%= ticket_url %> diff --git a/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_update/en.txt.erb b/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_update/en.txt.erb new file mode 100644 index 0000000..3e87f33 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/views/signal_notification/ticket_update/en.txt.erb @@ -0,0 +1,14 @@ +[Ticket #<%= ticket.number %>] <%= ticket.title %> + +TICKET UPDATED by <%= current_user.fullname %> +<% if changes.present? -%> + +Changes: +<%= changes_summary %> +<% end -%> +<% if article -%> + +<%= article_body_preview(500) %> +<% end -%> + +<%= ticket_url_with_article %> diff --git a/packages/zammad-addon-bridge/src/db/addon/bridge/20260120000001_add_signal_notification_settings.rb b/packages/zammad-addon-bridge/src/db/addon/bridge/20260120000001_add_signal_notification_settings.rb new file mode 100644 index 0000000..9e1bf23 --- /dev/null +++ b/packages/zammad-addon-bridge/src/db/addon/bridge/20260120000001_add_signal_notification_settings.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +class AddSignalNotificationSettings < ActiveRecord::Migration[5.2] + def self.up + # Register Signal notification transaction backend + # Using 0105 to run after email notifications (0100) + Setting.create_if_not_exists( + title: 'Defines transaction backend.', + name: '0105_signal_notification', + area: 'Transaction::Backend::Async', + description: 'Defines the transaction backend to send Signal notifications.', + options: {}, + state: 'Transaction::SignalNotification', + frontend: false + ) + + # Global enable/disable for Signal notifications + Setting.create_if_not_exists( + title: 'Signal Notifications', + name: 'signal_notification_enabled', + area: 'Integration::Switch', + description: 'Enable or disable Signal notifications for agents.', + options: { + form: [ + { + display: '', + null: true, + name: 'signal_notification_enabled', + tag: 'boolean', + options: { + true => 'yes', + false => 'no', + }, + }, + ], + }, + state: false, + preferences: { + prio: 1, + permission: ['admin.integration'], + }, + frontend: true + ) + + # Which Signal channel/bot to use for sending notifications + Setting.create_if_not_exists( + title: 'Signal Notification Channel', + name: 'signal_notification_channel_id', + area: 'Integration::SignalNotification', + description: 'The Signal channel (bot) used to send notifications to agents.', + options: {}, + state: nil, + preferences: { + prio: 2, + permission: ['admin.integration'], + }, + frontend: false + ) + + # Permission for Signal notifications profile page + Permission.create_if_not_exists( + name: 'user_preferences.signal_notifications', + description: 'Manage Signal notification preferences', + preferences: { + translations: ['Profile - Signal Notifications'] + } + ) + end + + def self.down + Setting.find_by(name: '0105_signal_notification')&.destroy + Setting.find_by(name: 'signal_notification_enabled')&.destroy + Setting.find_by(name: 'signal_notification_channel_id')&.destroy + Permission.find_by(name: 'user_preferences.signal_notifications')&.destroy + end +end diff --git a/packages/zammad-addon-bridge/src/lib/signal_notification_sender.rb b/packages/zammad-addon-bridge/src/lib/signal_notification_sender.rb new file mode 100644 index 0000000..8528892 --- /dev/null +++ b/packages/zammad-addon-bridge/src/lib/signal_notification_sender.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true + +require 'erb' + +class SignalNotificationSender + TEMPLATE_DIR = Rails.root.join('app', 'views', 'signal_notification') + + class << self + def build_message(ticket:, article:, user:, type:, changes:) + template_name = template_for_type(type) + return if template_name.blank? + + locale = user.locale || Setting.get('locale_default') || 'en' + template_path = find_template(template_name, locale) + return if template_path.blank? + + render_template(template_path, binding_for(ticket, article, user, changes)) + end + + def send_message(channel:, recipient:, message:) + return if Rails.env.test? + return if channel.blank? + return if recipient.blank? + return if message.blank? + + api_url = channel.options[:api_url] + api_token = channel.options[:api_token] + + return if api_url.blank? || api_token.blank? + + api = CdrSignalApi.new(api_url, api_token) + api.send_message(recipient, message) + end + + private + + def template_for_type(type) + case type + when 'create' + 'ticket_create' + when 'update', 'update.merged_into', 'update.received_merge', 'update.reaction' + 'ticket_update' + when 'reminder_reached' + 'ticket_reminder_reached' + when 'escalation', 'escalation_warning' + 'ticket_escalation' + end + end + + def find_template(template_name, locale) + base_locale = locale.split('-').first + + [locale, base_locale, 'en'].uniq.each do |try_locale| + path = TEMPLATE_DIR.join(template_name, "#{try_locale}.txt.erb") + return path if File.exist?(path) + end + + nil + end + + def binding_for(ticket, article, user, changes) + TemplateContext.new( + ticket: ticket, + article: article, + user: user, + changes: changes, + config: { + http_type: Setting.get('http_type'), + fqdn: Setting.get('fqdn'), + product_name: Setting.get('product_name') + } + ).get_binding + end + + def render_template(template_path, binding) + template = File.read(template_path) + erb = ERB.new(template, trim_mode: '-') + erb.result(binding).strip + end + end + + class TemplateContext + attr_reader :ticket, :article, :recipient, :changes, :config + + def initialize(ticket:, article:, user:, changes:, config:) + @ticket = ticket + @article = article + @recipient = user + @changes = changes + @config = OpenStruct.new(config) + end + + def get_binding + binding + end + + def ticket_url + "#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}" + end + + def ticket_url_with_article + if article + "#{ticket_url}/#{article.id}" + else + ticket_url + end + end + + def current_user + @current_user ||= User.lookup(id: ticket.updated_by_id) || User.lookup(id: 1) + end + + def changes_summary + return '' if changes.blank? + + changes.map { |key, values| "#{key}: #{values[0]} -> #{values[1]}" }.join("\n") + end + + def article_body_preview(max_length = 500) + return '' unless article + return '' if article.body.blank? + + body = article.body.to_s + body = ActionController::Base.helpers.strip_tags(body) if article.content_type&.include?('html') + body = body.gsub(/\s+/, ' ').strip + + if body.length > max_length + "#{body[0, max_length]}..." + else + body + end + end + + def t(text) + locale = recipient.locale || Setting.get('locale_default') || 'en' + Translation.translate(locale, text) + end + end +end From d93797172aba989bce1fa3891b2a8e30b5522f16 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Wed, 28 Jan 2026 14:46:34 +0100 Subject: [PATCH 22/38] Add preference for signal notifications to bot setup screen --- apps/link/Dockerfile | 5 +- .../controllers/_channel/cdr_signal.coffee | 29 + .../app/views/cdr_signal/index.jst.eco | 8 + .../channels_cdr_signal_controller.rb | 26 +- .../src/app/jobs/signal_notification_job.rb | 2 +- .../models/transaction/signal_notification.rb | 2 +- .../src/config/routes/channel_cdr_signal.rb | 2 + packages/zammad-addon-bridge/turbo.json | 9 + packages/zammad-addon-hardening/turbo.json | 9 + pnpm-lock.yaml | 2354 ++++++++--------- 10 files changed, 1232 insertions(+), 1214 deletions(-) create mode 100644 packages/zammad-addon-bridge/turbo.json create mode 100644 packages/zammad-addon-hardening/turbo.json diff --git a/apps/link/Dockerfile b/apps/link/Dockerfile index 689fffe..98523f4 100644 --- a/apps/link/Dockerfile +++ b/apps/link/Dockerfile @@ -42,10 +42,11 @@ RUN corepack enable && corepack prepare pnpm@9.15.4 --activate RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ apt-get install -y --no-install-recommends \ dumb-init -RUN mkdir -p ${APP_DIR} -RUN chown -R node ${APP_DIR}/ +RUN mkdir -p ${APP_DIR} /pnpm +RUN chown -R node ${APP_DIR}/ /pnpm USER node +RUN corepack prepare pnpm@9.15.4 --activate WORKDIR ${APP_DIR} COPY --from=installer ${APP_DIR} ./ USER root diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_channel/cdr_signal.coffee b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_channel/cdr_signal.coffee index f8f8028..3ed6865 100644 --- a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_channel/cdr_signal.coffee +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_channel/cdr_signal.coffee @@ -7,6 +7,8 @@ class ChannelCdrSignal extends App.ControllerSubContent 'click .js-disable': 'disable' 'click .js-enable': 'enable' 'click .js-rotate-token': 'rotateToken' + 'click .js-set-notification': 'setNotification' + 'click .js-unset-notification': 'unsetNotification' constructor: -> super @@ -41,6 +43,8 @@ class ChannelCdrSignal extends App.ControllerSubContent channels.push channel @html App.view('cdr_signal/index')( channels: channels + notificationEnabled: data.notification_enabled + notificationChannelId: data.notification_channel_id ) new: (e) => @@ -124,6 +128,31 @@ class ChannelCdrSignal extends App.ControllerSubContent @load() ) + setNotification: (e) => + e.preventDefault() + id = $(e.target).closest('.action').data('id') + @ajax( + id: 'cdr_signal_set_notification' + type: 'POST' + url: "#{@apiPath}/channels_cdr_signal_set_notification" + data: JSON.stringify(id: id) + processData: true + success: => + @load() + ) + + unsetNotification: (e) => + e.preventDefault() + @ajax( + id: 'cdr_signal_unset_notification' + type: 'POST' + url: "#{@apiPath}/channels_cdr_signal_unset_notification" + data: JSON.stringify({}) + processData: true + success: => + @load() + ) + class FormAdd extends App.ControllerModal head: 'Add Web Form' shown: true diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/cdr_signal/index.jst.eco b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/cdr_signal/index.jst.eco index 9bd157e..f8ae206 100644 --- a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/cdr_signal/index.jst.eco +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/cdr_signal/index.jst.eco @@ -20,6 +20,9 @@

<%- @Icon('status', 'supergood-color inline') %> <%= channel.options.phone_number %>

+ <% if @notificationEnabled and @notificationChannelId is channel.id: %> + <%- @T('Agent Notifications') %> + <% end %>
@@ -42,6 +45,11 @@ <% else: %>
<%- @T('Enable') %>
<% end %> + <% if @notificationEnabled and @notificationChannelId is channel.id: %> +
<%- @T('Disable Agent Notifications') %>
+ <% else if channel.active is true: %> +
<%- @T('Use for Agent Notifications') %>
+ <% end %>
<%- @T('Edit') %>
diff --git a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb index 16df77b..8b5dae0 100644 --- a/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb +++ b/packages/zammad-addon-bridge/src/app/controllers/channels_cdr_signal_controller.rb @@ -15,10 +15,34 @@ class ChannelsCdrSignalController < ApplicationController end render json: { assets: assets, - channel_ids: channel_ids + channel_ids: channel_ids, + notification_enabled: Setting.get('signal_notification_enabled') == true, + notification_channel_id: Setting.get('signal_notification_channel_id') } end + def set_notification_channel + channel_id = params[:id].to_i + channel = Channel.find_by(id: channel_id, area: 'Signal::Number') + + unless channel + render json: { error: 'Channel not found' }, status: :not_found + return + end + + Setting.set('signal_notification_channel_id', channel_id) + Setting.set('signal_notification_enabled', true) + + render json: { success: true, notification_channel_id: channel_id } + end + + def unset_notification_channel + Setting.set('signal_notification_enabled', false) + Setting.set('signal_notification_channel_id', nil) + + render json: { success: true } + end + def add begin errors = {} diff --git a/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb b/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb index 1da1012..7c23a3c 100644 --- a/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb +++ b/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb @@ -45,7 +45,7 @@ class SignalNotificationJob < ApplicationJob channel_id = Setting.get('signal_notification_channel_id') return unless channel_id - Channel.find_by(id: channel_id, area: 'Signal::Account', active: true) + Channel.find_by(id: channel_id, area: 'Signal::Number', active: true) end def add_history(ticket, user, type) diff --git a/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb b/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb index a7b9f29..415c441 100644 --- a/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb +++ b/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb @@ -63,7 +63,7 @@ class Transaction::SignalNotification channel_id = Setting.get('signal_notification_channel_id') return unless channel_id - Channel.find_by(id: channel_id, area: 'Signal::Account', active: true) + Channel.find_by(id: channel_id, area: 'Signal::Number', active: true) end end diff --git a/packages/zammad-addon-bridge/src/config/routes/channel_cdr_signal.rb b/packages/zammad-addon-bridge/src/config/routes/channel_cdr_signal.rb index b7df05b..414056c 100644 --- a/packages/zammad-addon-bridge/src/config/routes/channel_cdr_signal.rb +++ b/packages/zammad-addon-bridge/src/config/routes/channel_cdr_signal.rb @@ -12,4 +12,6 @@ Zammad::Application.routes.draw do match "#{api_path}/channels_cdr_signal_enable", to: 'channels_cdr_signal#enable', via: :post match "#{api_path}/channels_cdr_signal", to: 'channels_cdr_signal#destroy', via: :delete match "#{api_path}/channels_cdr_signal_rotate_token", to: 'channels_cdr_signal#rotate_token', via: :post + match "#{api_path}/channels_cdr_signal_set_notification", to: 'channels_cdr_signal#set_notification_channel', via: :post + match "#{api_path}/channels_cdr_signal_unset_notification", to: 'channels_cdr_signal#unset_notification_channel', via: :post end diff --git a/packages/zammad-addon-bridge/turbo.json b/packages/zammad-addon-bridge/turbo.json new file mode 100644 index 0000000..109f7c8 --- /dev/null +++ b/packages/zammad-addon-bridge/turbo.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"], + "tasks": { + "build": { + "outputs": ["../../docker/zammad/addons/zammad-addon-bridge-v*.zpm"] + } + } +} diff --git a/packages/zammad-addon-hardening/turbo.json b/packages/zammad-addon-hardening/turbo.json new file mode 100644 index 0000000..3d96279 --- /dev/null +++ b/packages/zammad-addon-hardening/turbo.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://turbo.build/schema.json", + "extends": ["//"], + "tasks": { + "build": { + "outputs": ["../../docker/zammad/addons/zammad-addon-hardening-v*.zpm"] + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 16f247c..3d701ab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,7 +26,7 @@ importers: version: 11.0.0 eslint: specifier: ^9 - version: 9.39.1 + version: 9.39.2 react: specifier: 19.2.0 version: 19.2.0 @@ -35,10 +35,10 @@ importers: version: 19.2.0(react@19.2.0) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@24.10.0)(typescript@5.9.3) + version: 10.9.2(@types/node@24.10.9)(typescript@5.9.3) turbo: - specifier: ^2.6.0 - version: 2.6.0 + specifier: ^2.5.8 + version: 2.7.6 typescript: specifier: latest version: 5.9.3 @@ -86,7 +86,7 @@ importers: version: 0.34.5 tsx: specifier: ^4.20.6 - version: 4.20.6 + version: 4.21.0 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -96,10 +96,10 @@ importers: version: link:../../packages/typescript-config '@types/node': specifier: ^24 - version: 24.10.0 + version: 24.10.9 '@types/pg': specifier: ^8.15.5 - version: 8.15.6 + version: 8.16.0 '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -123,10 +123,10 @@ importers: version: 0.27.5 pg: specifier: ^8.16.3 - version: 8.16.3 + version: 8.17.2 tsx: specifier: ^4.20.6 - version: 4.20.6 + version: 4.21.0 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -136,16 +136,19 @@ importers: version: link:../../packages/typescript-config '@types/node': specifier: ^24 - version: 24.10.0 + version: 24.10.9 '@types/pg': specifier: ^8.15.5 - version: 8.15.6 + version: 8.16.0 typescript: specifier: ^5 version: 5.9.3 apps/bridge-whatsapp: dependencies: + '@adiwajshing/keyed-db': + specifier: 0.2.4 + version: 0.2.4 '@hapi/hapi': specifier: ^21.4.3 version: 21.4.4 @@ -162,14 +165,14 @@ importers: specifier: workspace:* version: link:../../packages/logger '@whiskeysockets/baileys': - specifier: 7.0.0-rc.9 - version: 7.0.0-rc.9(link-preview-js@3.1.0)(sharp@0.34.5) + specifier: 6.7.21 + version: 6.7.21(link-preview-js@3.2.0)(sharp@0.34.5) hapi-pino: specifier: ^13.0.0 version: 13.0.0 link-preview-js: specifier: ^3.1.0 - version: 3.1.0 + version: 3.2.0 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -180,9 +183,18 @@ importers: '@link-stack/typescript-config': specifier: workspace:* version: link:../../packages/typescript-config + '@types/long': + specifier: ^5 + version: 5.0.0 '@types/node': specifier: '*' - version: 24.10.0 + version: 24.10.9 + dotenv-cli: + specifier: ^10.0.0 + version: 10.0.0 + tsx: + specifier: ^4.20.6 + version: 4.21.0 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -209,10 +221,10 @@ importers: version: 0.16.6(typescript@5.9.3) remeda: specifier: ^2.32.0 - version: 2.32.0 + version: 2.33.4 twilio: specifier: ^5.10.2 - version: 5.10.4 + version: 5.12.0 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -273,7 +285,7 @@ importers: version: 6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) '@mui/x-data-grid-pro': specifier: ^7 - version: 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-date-pickers': specifier: ^7 version: 7.29.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(date-fns@4.1.0)(dayjs@1.11.19)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -288,10 +300,10 @@ importers: version: 4.1.0 graphql-request: specifier: ^7.2.0 - version: 7.3.1(graphql@16.12.0) + version: 7.4.0(graphql@16.12.0) ioredis: specifier: ^5.8.1 - version: 5.8.2 + version: 5.9.2 mui-chips-input: specifier: ^6.0.0 version: 6.0.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/icons-material@6.5.0(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -325,7 +337,7 @@ importers: version: link:../../packages/eslint-config '@types/node': specifier: ^24.7.0 - version: 24.10.0 + version: 24.10.9 '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -343,7 +355,7 @@ importers: version: 0.27.5 pg: specifier: ^8.16.3 - version: 8.16.3 + version: 8.17.2 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -353,7 +365,7 @@ importers: version: link:../typescript-config '@types/pg': specifier: ^8.15.5 - version: 8.15.6 + version: 8.16.0 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -374,7 +386,7 @@ importers: version: 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-data-grid-pro': specifier: ^7 - version: 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) kysely: specifier: 0.27.5 version: 0.27.5 @@ -393,7 +405,7 @@ importers: devDependencies: '@types/node': specifier: ^24.7.0 - version: 24.10.0 + version: 24.10.9 '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -408,44 +420,44 @@ importers: dependencies: '@babel/eslint-parser': specifier: 7.28.4 - version: 7.28.4(@babel/core@7.28.5)(eslint@9.39.1) + version: 7.28.4(@babel/core@7.28.6)(eslint@9.39.2) '@rushstack/eslint-patch': specifier: ^1.13.0 - version: 1.14.1 + version: 1.15.0 '@typescript-eslint/eslint-plugin': specifier: ^8.46.0 - version: 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) + version: 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) '@typescript-eslint/parser': specifier: ^8.46.0 - version: 8.46.3(eslint@9.39.1)(typescript@5.9.3) + version: 8.54.0(eslint@9.39.2)(typescript@5.9.3) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.1) + version: 10.1.8(eslint@9.39.2) eslint-config-xo-space: specifier: ^0.35.0 - version: 0.35.0(eslint@9.39.1) + version: 0.35.0(eslint@9.39.2) eslint-plugin-eslint-comments: specifier: ^3.2.0 - version: 3.2.0(eslint@9.39.1) + version: 3.2.0(eslint@9.39.2) eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1) + version: 2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) eslint-plugin-jest: specifier: ^29.0.1 - version: 29.0.1(@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)))(typescript@5.9.3) + version: 29.12.1(@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(jest@30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)))(typescript@5.9.3) eslint-plugin-promise: specifier: ^7.2.1 - version: 7.2.1(eslint@9.39.1) + version: 7.2.1(eslint@9.39.2) eslint-plugin-unicorn: specifier: 61.0.2 - version: 61.0.2(eslint@9.39.1) + version: 61.0.2(eslint@9.39.2) devDependencies: eslint: specifier: ^9 - version: 9.39.1 + version: 9.39.2 jest: specifier: ^30.2.0 - version: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) + version: 30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -457,7 +469,7 @@ importers: version: 30.0.0 jest: specifier: ^30.2.0 - version: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) + version: 30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)) jest-junit: specifier: ^16.0.0 version: 16.0.0 @@ -466,10 +478,10 @@ importers: dependencies: pino: specifier: ^10.0.0 - version: 10.1.0 + version: 10.3.0 pino-pretty: specifier: ^13.1.1 - version: 13.1.2 + version: 13.1.3 devDependencies: '@link-stack/eslint-config': specifier: workspace:* @@ -479,13 +491,13 @@ importers: version: link:../typescript-config '@types/node': specifier: ^24.7.0 - version: 24.10.0 + version: 24.10.9 eslint: specifier: ^9.37.0 - version: 9.39.1 + version: 9.39.2 tsup: specifier: ^8.5.0 - version: 8.5.0(postcss@8.4.31)(tsx@4.20.6)(typescript@5.9.3) + version: 8.5.1(postcss@8.4.31)(tsx@4.21.0)(typescript@5.9.3) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -500,10 +512,10 @@ importers: version: link:../typescript-config '@openapitools/openapi-generator-cli': specifier: ^2.24.0 - version: 2.25.0(@types/node@24.10.0) + version: 2.28.0(@types/node@24.10.9) '@types/node': specifier: ^24 - version: 24.10.0 + version: 24.10.9 typescript: specifier: ^5 version: 5.9.3 @@ -520,7 +532,7 @@ importers: version: 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-data-grid-pro': specifier: ^7 - version: 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-license': specifier: ^7 version: 7.29.1(@types/react@19.2.2)(react@19.2.0) @@ -536,7 +548,7 @@ importers: devDependencies: '@types/node': specifier: ^24.7.0 - version: 24.10.0 + version: 24.10.9 '@types/react': specifier: 19.2.2 version: 19.2.2 @@ -560,11 +572,11 @@ importers: version: link:../logger glob: specifier: ^11.0.3 - version: 11.0.3 + version: 11.1.0 devDependencies: '@types/node': specifier: ^24.7.0 - version: 24.10.0 + version: 24.10.9 typescript: specifier: ^5 version: 5.9.3 @@ -577,6 +589,9 @@ importers: packages: + '@adiwajshing/keyed-db@0.2.4': + resolution: {integrity: sha512-yprSnAtj80/VKuDqRcFFLDYltoNV8tChNwFfIgcf6PGD4sjzWIBgs08pRuTqGH5mk5wgL6PBRSsMCZqtZwzFEw==} + '@auth/core@0.41.1': resolution: {integrity: sha512-t9cJ2zNYAdWMacGRMT6+r4xr1uybIdmYa49calBPeTqwgAFPV/88ac9TEvCR85pvATiSPt8VaNf+Gt24JIT/uw==} peerDependencies: @@ -596,16 +611,16 @@ packages: peerDependencies: kysely: ^0.27.5 - '@babel/code-frame@7.27.1': - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + '@babel/code-frame@7.28.6': + resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.5': - resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} + '@babel/compat-data@7.28.6': + resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.5': - resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + '@babel/core@7.28.6': + resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} engines: {node: '>=6.9.0'} '@babel/eslint-parser@7.28.4': @@ -615,30 +630,30 @@ packages: '@babel/core': ^7.11.0 eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - '@babel/generator@7.28.5': - resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + '@babel/generator@7.28.6': + resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.27.2': - resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} engines: {node: '>=6.9.0'} '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.27.1': - resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.28.3': - resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.27.1': - resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.27.1': @@ -653,12 +668,12 @@ packages: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.28.4': - resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + '@babel/helpers@7.28.6': + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.5': - resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + '@babel/parser@7.28.6': + resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -683,8 +698,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.27.1': - resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -699,8 +714,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.27.1': - resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -747,49 +762,43 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-typescript@7.27.1': - resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.28.4': - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} engines: {node: '>=6.9.0'} - '@babel/template@7.27.2': - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.28.5': - resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + '@babel/traverse@7.28.6': + resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} engines: {node: '>=6.9.0'} - '@babel/types@7.28.5': - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + '@babel/types@7.28.6': + resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@borewit/text-codec@0.1.1': - resolution: {integrity: sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==} + '@borewit/text-codec@0.2.1': + resolution: {integrity: sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==} - '@borewit/text-codec@0.2.0': - resolution: {integrity: sha512-X999CKBxGwX8wW+4gFibsbiNdwqmdQEXmUejIWaIqdrHBgS5ARIOOeyiQbHjP9G58xVEPcuvP6VwwH3A0OFTOA==} + '@cacheable/memory@2.0.7': + resolution: {integrity: sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A==} - '@cacheable/memoize@2.0.3': - resolution: {integrity: sha512-hl9wfQgpiydhQEIv7fkjEzTGE+tcosCXLKFDO707wYJ/78FVOlowb36djex5GdbSyeHnG62pomYLMuV/OT8Pbw==} - - '@cacheable/memory@2.0.4': - resolution: {integrity: sha512-cCmJKCKlT1t7hNBI1+gFCwmKFd9I4pS3zqBeNGXTSODnpa0EeDmORHY8oEMTuozfdg3cgsVh8ojLaPYb6eC7Cg==} - - '@cacheable/node-cache@1.7.4': - resolution: {integrity: sha512-XU3iQNHcIY2P6GlPCr8iScJV8I4S5hRU6sSQpNOKCLi5Q0VcdMEYa6b6vfNMXyqXI9IFzG44SE+RaxrN+5+ROw==} + '@cacheable/node-cache@1.7.6': + resolution: {integrity: sha512-6Omk2SgNnjtxB5f/E6bTIWIt5xhdpx39fGNRQgU9lojvRxU68v+qY+SXXLsp3ZGukqoPjsK21wZ6XABFr/Ge3A==} engines: {node: '>=18'} - '@cacheable/utils@2.2.0': - resolution: {integrity: sha512-7xaQayO3msdVcxXLYcLU5wDqJBNdQcPPPHr6mdTEIQI7N7TbtSVVTpWOTfjyhg0L6AQwQdq7miKdWtTDBoBldQ==} + '@cacheable/utils@2.3.3': + resolution: {integrity: sha512-JsXDL70gQ+1Vc2W/KUFfkAJzgb4puKwwKehNLuB+HrNKWf91O736kGfxn4KujXCCSuh6mRRL4XEB0PkAFjWS0A==} '@chatscope/chat-ui-kit-react@2.1.1': resolution: {integrity: sha512-rCtE9abdmAbBDkAAUYBC1TDTBMZHquqFIZhADptAfHcJ8z8W3XH/z/ZuwBSJXtzi6h1mwCNc3tBmm1A2NLGhNg==} @@ -805,11 +814,11 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@emnapi/core@1.7.0': - resolution: {integrity: sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw==} + '@emnapi/core@1.8.1': + resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} - '@emnapi/runtime@1.7.0': - resolution: {integrity: sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==} + '@emnapi/runtime@1.8.1': + resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} @@ -876,164 +885,164 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.9.0': - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -1058,12 +1067,12 @@ packages: resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.1': - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.39.1': - resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} + '@eslint/js@9.39.2': + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': @@ -1096,6 +1105,7 @@ packages: '@fortawesome/react-fontawesome@0.2.6': resolution: {integrity: sha512-mtBFIi1UsYQo7rYonYFkjgYKGoL8T+fEH6NGUpvuqtY3ytMsAoDaPo5rk25KuMtKDipY4bGYM/CkmCHA1N3FUg==} + deprecated: v0.2.x is no longer supported. Unless you are still using FontAwesome 5, please update to v3.1.1 or greater. peerDependencies: '@fortawesome/fontawesome-svg-core': ~1 || ~6 || ~7 react: 19.2.0 @@ -1141,8 +1151,8 @@ packages: '@hapi/content@6.0.0': resolution: {integrity: sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==} - '@hapi/cryptiles@6.0.1': - resolution: {integrity: sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ==} + '@hapi/cryptiles@6.0.3': + resolution: {integrity: sha512-r6VKalpbMHz4ci3gFjFysBmhwCg70RpYZy6OkjEpdXzAYnYFX5XsW7n4YMJvuIYpnMwLxGUjK/cBhA7X3JDvXw==} engines: {node: '>=14.0.0'} '@hapi/file@3.0.0': @@ -1382,8 +1392,8 @@ packages: '@types/node': optional: true - '@ioredis/commands@1.4.0': - resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==} + '@ioredis/commands@1.5.0': + resolution: {integrity: sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==} '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} @@ -1506,11 +1516,11 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@keyv/bigmap@1.1.0': - resolution: {integrity: sha512-MX7XIUNwVRK+hjZcAbNJ0Z8DREo+Weu9vinBOjGU1thEi9F6vPhICzBbk4CCf3eEefKRz7n6TfZXwUFZTSgj8Q==} + '@keyv/bigmap@1.3.1': + resolution: {integrity: sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==} engines: {node: '>= 18'} peerDependencies: - keyv: ^5.5.3 + keyv: ^5.6.0 '@keyv/serialize@1.1.1': resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} @@ -1618,8 +1628,8 @@ packages: '@types/react': optional: true - '@mui/types@7.4.8': - resolution: {integrity: sha512-ZNXLBjkPV6ftLCmmRCafak3XmSn8YV0tKE/ZOhzKys7TZXUiE0mZxlH8zKDo6j6TTUaDnuij68gIG+0Ucm7Xhw==} + '@mui/types@7.4.10': + resolution: {integrity: sha512-0+4mSjknSu218GW3isRqoxKRTOrTLd/vHi/7UC4+wZcUrOAqD9kRk7UQRL1mcrzqRoe7s3UT6rsRpbLkW5mHpQ==} peerDependencies: '@types/react': 19.2.2 peerDependenciesMeta: @@ -1636,8 +1646,8 @@ packages: '@types/react': optional: true - '@mui/utils@7.3.5': - resolution: {integrity: sha512-jisvFsEC3sgjUjcPnR4mYfhzjCDIudttSGSbe1o/IXFNu0kZuR+7vqQI0jg8qtcVZBHWrwTfvAZj9MNMumcq1g==} + '@mui/utils@7.3.7': + resolution: {integrity: sha512-+YjnjMRnyeTkWnspzoxRdiSOgkrcpTikhNPoxOZW0APXx+urHtUoXJ9lbtCZRCA5a4dg5gSbd19alL1DvRs5fg==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': 19.2.2 @@ -1646,8 +1656,8 @@ packages: '@types/react': optional: true - '@mui/x-data-grid-pro@7.29.9': - resolution: {integrity: sha512-ulh/hvvSboZZfHS+ajM0rtRTsBAmQEh519GHjkFfyTdn94o6a+4pFhhuBFN0toyj6264HV0NLs5FJp/zx+bEwA==} + '@mui/x-data-grid-pro@7.29.12': + resolution: {integrity: sha512-HoBaqJYqxaVZCkv3NK1qdca0Sv2er6L2Wrt51gyfMBBuM+liSpQ0L4HqX42bzIst+ScAoBpBAn6ILm9RQ0rqLw==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.9.0 @@ -1662,8 +1672,8 @@ packages: '@emotion/styled': optional: true - '@mui/x-data-grid@7.29.9': - resolution: {integrity: sha512-RfK7Fnuu4eyv/4eD3MEB1xxZsx0xRBsofb1kifghIjyQV1EKAeRcwvczyrzQggj7ZRT5AqkwCzhLsZDvE5O0nQ==} + '@mui/x-data-grid@7.29.12': + resolution: {integrity: sha512-MaEC7ubr/je8jVWjdRU7LxBXAzlOZwFEdNdvlDUJIYkRa3TRCQ1HsY8Gd8Od0jnlnMYn9M4BrEfOrq9VRnt4bw==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.9.0 @@ -1774,8 +1784,8 @@ packages: axios: ^1.3.1 rxjs: ^7.0.0 - '@nestjs/common@11.1.6': - resolution: {integrity: sha512-krKwLLcFmeuKDqngG2N/RuZHCs2ycsKcxWIDgcm7i1lf3sQ0iG03ci+DsP/r3FcT/eJDFsIHnKtNta2LIi7PzQ==} + '@nestjs/common@11.1.12': + resolution: {integrity: sha512-v6U3O01YohHO+IE3EIFXuRuu3VJILWzyMmSYZXpyBbnp0hk0mFyHxK2w3dF4I5WnbwiRbWlEXdeXFvPQ7qaZzw==} peerDependencies: class-transformer: '>=0.4.1' class-validator: '>=0.13.2' @@ -1787,8 +1797,8 @@ packages: class-validator: optional: true - '@nestjs/core@11.1.6': - resolution: {integrity: sha512-siWX7UDgErisW18VTeJA+x+/tpNZrJewjTBsRPF3JVxuWRuAB1kRoiJcxHgln8Lb5UY9NdvklITR84DUEXD0Cg==} + '@nestjs/core@11.1.12': + resolution: {integrity: sha512-97DzTYMf5RtGAVvX1cjwpKRiCUpkeQ9CCzSAenqkAhOmNVVFaApbhuw+xrDt13rsCa2hHVOYPrV4dBgOYMJjsA==} engines: {node: '>= 20'} peerDependencies: '@nestjs/common': ^11.0.0 @@ -1859,18 +1869,6 @@ packages: '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - '@nuxt/opencollective@0.4.1': resolution: {integrity: sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==} engines: {node: ^14.18.0 || >=16.10.0, npm: '>=5.10.0'} @@ -1881,8 +1879,8 @@ packages: engines: {node: '>=8.0.0', npm: '>=5.0.0'} hasBin: true - '@openapitools/openapi-generator-cli@2.25.0': - resolution: {integrity: sha512-u/3VAbF8c68AXBgm8nBAdDPLPW/KgrtHz28yemf92zNB0iDZFGdRUX2W80Lzf177g6ctYLz0GIPHCOU0LTJegQ==} + '@openapitools/openapi-generator-cli@2.28.0': + resolution: {integrity: sha512-eWLMHYGxaRSO8NCIovYeRiT1JFWjVzcLdxPpaCGUiIWOFUW4gnPHOppPp4x0adFRji6dTezg9L4Cm4tHSaftgQ==} engines: {node: '>=16'} hasBin: true @@ -1933,124 +1931,139 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@rollup/rollup-android-arm-eabi@4.53.1': - resolution: {integrity: sha512-bxZtughE4VNVJlL1RdoSE545kc4JxL7op57KKoi59/gwuU5rV6jLWFXXc8jwgFoT6vtj+ZjO+Z2C5nrY0Cl6wA==} + '@rollup/rollup-android-arm-eabi@4.57.0': + resolution: {integrity: sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.53.1': - resolution: {integrity: sha512-44a1hreb02cAAfAKmZfXVercPFaDjqXCK+iKeVOlJ9ltvnO6QqsBHgKVPTu+MJHSLLeMEUbeG2qiDYgbFPU48g==} + '@rollup/rollup-android-arm64@4.57.0': + resolution: {integrity: sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.53.1': - resolution: {integrity: sha512-usmzIgD0rf1syoOZ2WZvy8YpXK5G1V3btm3QZddoGSa6mOgfXWkkv+642bfUUldomgrbiLQGrPryb7DXLovPWQ==} + '@rollup/rollup-darwin-arm64@4.57.0': + resolution: {integrity: sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.1': - resolution: {integrity: sha512-is3r/k4vig2Gt8mKtTlzzyaSQ+hd87kDxiN3uDSDwggJLUV56Umli6OoL+/YZa/KvtdrdyNfMKHzL/P4siOOmg==} + '@rollup/rollup-darwin-x64@4.57.0': + resolution: {integrity: sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.53.1': - resolution: {integrity: sha512-QJ1ksgp/bDJkZB4daldVmHaEQkG4r8PUXitCOC2WRmRaSaHx5RwPoI3DHVfXKwDkB+Sk6auFI/+JHacTekPRSw==} + '@rollup/rollup-freebsd-arm64@4.57.0': + resolution: {integrity: sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.1': - resolution: {integrity: sha512-J6ma5xgAzvqsnU6a0+jgGX/gvoGokqpkx6zY4cWizRrm0ffhHDpJKQgC8dtDb3+MqfZDIqs64REbfHDMzxLMqQ==} + '@rollup/rollup-freebsd-x64@4.57.0': + resolution: {integrity: sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.53.1': - resolution: {integrity: sha512-JzWRR41o2U3/KMNKRuZNsDUAcAVUYhsPuMlx5RUldw0E4lvSIXFUwejtYz1HJXohUmqs/M6BBJAUBzKXZVddbg==} + '@rollup/rollup-linux-arm-gnueabihf@4.57.0': + resolution: {integrity: sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.53.1': - resolution: {integrity: sha512-L8kRIrnfMrEoHLHtHn+4uYA52fiLDEDyezgxZtGUTiII/yb04Krq+vk3P2Try+Vya9LeCE9ZHU8CXD6J9EhzHQ==} + '@rollup/rollup-linux-arm-musleabihf@4.57.0': + resolution: {integrity: sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.53.1': - resolution: {integrity: sha512-ysAc0MFRV+WtQ8li8hi3EoFi7us6d1UzaS/+Dp7FYZfg3NdDljGMoVyiIp6Ucz7uhlYDBZ/zt6XI0YEZbUO11Q==} + '@rollup/rollup-linux-arm64-gnu@4.57.0': + resolution: {integrity: sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.53.1': - resolution: {integrity: sha512-UV6l9MJpDbDZZ/fJvqNcvO1PcivGEf1AvKuTcHoLjVZVFeAMygnamCTDikCVMRnA+qJe+B3pSbgX2+lBMqgBhA==} + '@rollup/rollup-linux-arm64-musl@4.57.0': + resolution: {integrity: sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.53.1': - resolution: {integrity: sha512-UDUtelEprkA85g95Q+nj3Xf0M4hHa4DiJ+3P3h4BuGliY4NReYYqwlc0Y8ICLjN4+uIgCEvaygYlpf0hUj90Yg==} + '@rollup/rollup-linux-loong64-gnu@4.57.0': + resolution: {integrity: sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.53.1': - resolution: {integrity: sha512-vrRn+BYhEtNOte/zbc2wAUQReJXxEx2URfTol6OEfY2zFEUK92pkFBSXRylDM7aHi+YqEPJt9/ABYzmcrS4SgQ==} + '@rollup/rollup-linux-loong64-musl@4.57.0': + resolution: {integrity: sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.57.0': + resolution: {integrity: sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.53.1': - resolution: {integrity: sha512-gto/1CxHyi4A7YqZZNznQYrVlPSaodOBPKM+6xcDSCMVZN/Fzb4K+AIkNz/1yAYz9h3Ng+e2fY9H6bgawVq17w==} + '@rollup/rollup-linux-ppc64-musl@4.57.0': + resolution: {integrity: sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.57.0': + resolution: {integrity: sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.53.1': - resolution: {integrity: sha512-KZ6Vx7jAw3aLNjFR8eYVcQVdFa/cvBzDNRFM3z7XhNNunWjA03eUrEwJYPk0G8V7Gs08IThFKcAPS4WY/ybIrQ==} + '@rollup/rollup-linux-riscv64-musl@4.57.0': + resolution: {integrity: sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.53.1': - resolution: {integrity: sha512-HvEixy2s/rWNgpwyKpXJcHmE7om1M89hxBTBi9Fs6zVuLU4gOrEMQNbNsN/tBVIMbLyysz/iwNiGtMOpLAOlvA==} + '@rollup/rollup-linux-s390x-gnu@4.57.0': + resolution: {integrity: sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.53.1': - resolution: {integrity: sha512-E/n8x2MSjAQgjj9IixO4UeEUeqXLtiA7pyoXCFYLuXpBA/t2hnbIdxHfA7kK9BFsYAoNU4st1rHYdldl8dTqGA==} + '@rollup/rollup-linux-x64-gnu@4.57.0': + resolution: {integrity: sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.53.1': - resolution: {integrity: sha512-IhJ087PbLOQXCN6Ui/3FUkI9pWNZe/Z7rEIVOzMsOs1/HSAECCvSZ7PkIbkNqL/AZn6WbZvnoVZw/qwqYMo4/w==} + '@rollup/rollup-linux-x64-musl@4.57.0': + resolution: {integrity: sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.53.1': - resolution: {integrity: sha512-0++oPNgLJHBblreu0SFM7b3mAsBJBTY0Ksrmu9N6ZVrPiTkRgda52mWR7TKhHAsUb9noCjFvAw9l6ZO1yzaVbA==} + '@rollup/rollup-openbsd-x64@4.57.0': + resolution: {integrity: sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.57.0': + resolution: {integrity: sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.53.1': - resolution: {integrity: sha512-VJXivz61c5uVdbmitLkDlbcTk9Or43YC2QVLRkqp86QoeFSqI81bNgjhttqhKNMKnQMWnecOCm7lZz4s+WLGpQ==} + '@rollup/rollup-win32-arm64-msvc@4.57.0': + resolution: {integrity: sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.1': - resolution: {integrity: sha512-NmZPVTUOitCXUH6erJDzTQ/jotYw4CnkMDjCYRxNHVD9bNyfrGoIse684F9okwzKCV4AIHRbUkeTBc9F2OOH5Q==} + '@rollup/rollup-win32-ia32-msvc@4.57.0': + resolution: {integrity: sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.1': - resolution: {integrity: sha512-2SNj7COIdAf6yliSpLdLG8BEsp5lgzRehgfkP0Av8zKfQFKku6JcvbobvHASPJu4f3BFxej5g+HuQPvqPhHvpQ==} + '@rollup/rollup-win32-x64-gnu@4.57.0': + resolution: {integrity: sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.53.1': - resolution: {integrity: sha512-rLarc1Ofcs3DHtgSzFO31pZsCh8g05R2azN1q3fF+H423Co87My0R+tazOEvYVKXSLh8C4LerMK41/K7wlklcg==} + '@rollup/rollup-win32-x64-msvc@4.57.0': + resolution: {integrity: sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ==} cpu: [x64] os: [win32] '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@rushstack/eslint-patch@1.14.1': - resolution: {integrity: sha512-jGTk8UD/RdjsNZW8qq10r0RBvxL8OWtoT+kImlzPDFilmozzM+9QmIJsmze9UiSBrFU45ZxhTYBypn9q9z/VfQ==} + '@rushstack/eslint-patch@1.15.0': + resolution: {integrity: sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==} - '@sinclair/typebox@0.34.41': - resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} + '@sinclair/typebox@0.34.48': + resolution: {integrity: sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==} '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} @@ -2061,8 +2074,8 @@ packages: '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@tokenizer/inflate@0.2.7': - resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} engines: {node: '>=18'} '@tokenizer/token@0.3.0': @@ -2071,8 +2084,8 @@ packages: '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} @@ -2115,8 +2128,8 @@ packages: peerDependencies: '@types/react': 19.2.2 - '@types/interpret@1.1.3': - resolution: {integrity: sha512-uBaBhj/BhilG58r64mtDb/BEdH51HIQLgP5bmWzc5qCtFMja8dCk/IOJmk36j0lbi9QHwI6sbtUNGuqXdKCAtQ==} + '@types/interpret@1.1.4': + resolution: {integrity: sha512-r+tPKWHYqaxJOYA3Eik0mMi+SEREqOXLmsooRFmc6GHv7nWUDixFtKN+cegvsPlDcEZd9wxsdp041v2imQuvag==} '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -2139,23 +2152,27 @@ packages: '@types/long@4.0.2': resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} + '@types/long@5.0.0': + resolution: {integrity: sha512-eQs9RsucA/LNjnMoJvWG/nXa7Pot/RbBzilF/QRIU/xRl+0ApxrSUFsV5lmf01SvSlqMzJ7Zwxe440wmz2SJGA==} + deprecated: This is a stub types definition. long provides its own type definitions, so you do not need this installed. + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} '@types/node@10.17.60': resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} - '@types/node@22.19.0': - resolution: {integrity: sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==} + '@types/node@22.19.7': + resolution: {integrity: sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==} - '@types/node@24.10.0': - resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==} + '@types/node@24.10.9': + resolution: {integrity: sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/pg@8.15.6': - resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} + '@types/pg@8.16.0': + resolution: {integrity: sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==} '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} @@ -2182,66 +2199,66 @@ packages: '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - '@types/yargs@17.0.34': - resolution: {integrity: sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==} + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - '@typescript-eslint/eslint-plugin@8.46.3': - resolution: {integrity: sha512-sbaQ27XBUopBkRiuY/P9sWGOWUW4rl8fDoHIUmLpZd8uldsTyB4/Zg6bWTegPoTLnKj9Hqgn3QD6cjPNB32Odw==} + '@typescript-eslint/eslint-plugin@8.54.0': + resolution: {integrity: sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.46.3 + '@typescript-eslint/parser': ^8.54.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.46.3': - resolution: {integrity: sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==} + '@typescript-eslint/parser@8.54.0': + resolution: {integrity: sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.46.3': - resolution: {integrity: sha512-Fz8yFXsp2wDFeUElO88S9n4w1I4CWDTXDqDr9gYvZgUpwXQqmZBr9+NTTql5R3J7+hrJZPdpiWaB9VNhAKYLuQ==} + '@typescript-eslint/project-service@8.54.0': + resolution: {integrity: sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.46.3': - resolution: {integrity: sha512-FCi7Y1zgrmxp3DfWfr+3m9ansUUFoy8dkEdeQSgA9gbm8DaHYvZCdkFRQrtKiedFf3Ha6VmoqoAaP68+i+22kg==} + '@typescript-eslint/scope-manager@8.54.0': + resolution: {integrity: sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.46.3': - resolution: {integrity: sha512-GLupljMniHNIROP0zE7nCcybptolcH8QZfXOpCfhQDAdwJ/ZTlcaBOYebSOZotpti/3HrHSw7D3PZm75gYFsOA==} + '@typescript-eslint/tsconfig-utils@8.54.0': + resolution: {integrity: sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.46.3': - resolution: {integrity: sha512-ZPCADbr+qfz3aiTTYNNkCbUt+cjNwI/5McyANNrFBpVxPt7GqpEYz5ZfdwuFyGUnJ9FdDXbGODUu6iRCI6XRXw==} + '@typescript-eslint/type-utils@8.54.0': + resolution: {integrity: sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.46.3': - resolution: {integrity: sha512-G7Ok9WN/ggW7e/tOf8TQYMaxgID3Iujn231hfi0Pc7ZheztIJVpO44ekY00b7akqc6nZcvregk0Jpah3kep6hA==} + '@typescript-eslint/types@8.54.0': + resolution: {integrity: sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.46.3': - resolution: {integrity: sha512-f/NvtRjOm80BtNM5OQtlaBdM5BRFUv7gf381j9wygDNL+qOYSNOgtQ/DCndiYi80iIOv76QqaTmp4fa9hwI0OA==} + '@typescript-eslint/typescript-estree@8.54.0': + resolution: {integrity: sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.46.3': - resolution: {integrity: sha512-VXw7qmdkucEx9WkmR3ld/u6VhRyKeiF1uxWwCy/iuNfokjJ7VhsgLSOTjsol8BunSw190zABzpwdNsze2Kpo4g==} + '@typescript-eslint/utils@8.54.0': + resolution: {integrity: sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.46.3': - resolution: {integrity: sha512-uk574k8IU0rOF/AjniX8qbLSGURJVUCeM5e4MIMKBFFi8weeiLrG1fyQejyLXQpRZbU/1BuQasleV/RfHC3hHg==} + '@typescript-eslint/visitor-keys@8.54.0': + resolution: {integrity: sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': @@ -2342,8 +2359,8 @@ packages: cpu: [x64] os: [win32] - '@whiskeysockets/baileys@7.0.0-rc.9': - resolution: {integrity: sha512-YFm5gKXfDP9byCXCW3OPHKXLzrAKzolzgVUlRosHHgwbnf2YOO3XknkMm6J7+F0ns8OA0uuSBhgkRHTDtqkacw==} + '@whiskeysockets/baileys@6.7.21': + resolution: {integrity: sha512-xx9OHd6jlPiu5yZVuUdwEgFNAOXiEG8sULHxC6XfzNwssnwxnA9Lp44pR05H621GQcKyCfsH33TGy+Na6ygX4w==} engines: {node: '>=20.0.0'} peerDependencies: audio-decode: ^2.1.3 @@ -2479,12 +2496,12 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axios@1.12.2: - resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} - axios@1.13.2: resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + axios@1.13.4: + resolution: {integrity: sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==} + babel-jest@30.2.0: resolution: {integrity: sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -2520,12 +2537,12 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.25: - resolution: {integrity: sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==} + baseline-browser-mapping@2.9.18: + resolution: {integrity: sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==} hasBin: true - basic-ftp@5.0.5: - resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + basic-ftp@5.1.0: + resolution: {integrity: sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==} engines: {node: '>=10.0.0'} bl@4.1.0: @@ -2544,8 +2561,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.27.0: - resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -2578,8 +2595,8 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - cacheable@2.1.1: - resolution: {integrity: sha512-LmF4AXiSNdiRbI2UjH8pAp9NIXxeQsTotpEaegPiDcnN0YPygDJDV3l/Urc0mL72JWdATEorKqIHEx55nDlONg==} + cacheable@2.3.2: + resolution: {integrity: sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==} call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} @@ -2605,8 +2622,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001754: - resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==} + caniuse-lite@1.0.30001766: + resolution: {integrity: sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -2637,8 +2654,8 @@ packages: resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} engines: {node: '>=8'} - cjs-module-lexer@2.1.1: - resolution: {integrity: sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ==} + cjs-module-lexer@2.2.0: + resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -2749,12 +2766,12 @@ packages: resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} - cookie@1.0.2: - resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} - core-js-compat@3.46.0: - resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==} + core-js-compat@3.48.0: + resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -2786,8 +2803,8 @@ packages: resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} engines: {node: '>= 6'} - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} curve25519-js@0.0.4: resolution: {integrity: sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==} @@ -2834,8 +2851,8 @@ packages: supports-color: optional: true - dedent@1.7.0: - resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==} + dedent@1.7.1: + resolution: {integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -2880,8 +2897,8 @@ packages: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + diff@4.0.4: + resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} engines: {node: '>=0.3.1'} doctrine@2.1.0: @@ -2944,8 +2961,8 @@ packages: ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} - electron-to-chromium@1.5.249: - resolution: {integrity: sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==} + electron-to-chromium@1.5.279: + resolution: {integrity: sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -2971,8 +2988,8 @@ packages: error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - es-abstract@1.24.0: - resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} + es-abstract@1.24.1: + resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} engines: {node: '>= 0.4'} es-define-property@1.0.1: @@ -2999,8 +3016,8 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} engines: {node: '>=18'} hasBin: true @@ -3083,8 +3100,8 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-jest@29.0.1: - resolution: {integrity: sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==} + eslint-plugin-jest@29.12.1: + resolution: {integrity: sha512-Rxo7r4jSANMBkXLICJKS0gjacgyopfNAsoS0e3R9AHnjoKuQOaaPfmsDJPi8UWwygI099OV/K/JhpYRVkxD4AA==} engines: {node: ^20.12.0 || ^22.0.0 || >=24.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': ^8.0.0 @@ -3128,8 +3145,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.39.1: - resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} + eslint@9.39.2: + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -3147,8 +3164,8 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -3167,9 +3184,6 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -3182,16 +3196,12 @@ packages: resolution: {integrity: sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - fast-copy@3.0.2: - resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + fast-copy@4.0.2: + resolution: {integrity: sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw==} fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -3201,9 +3211,6 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fastq@1.19.1: - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} @@ -3216,9 +3223,6 @@ packages: picomatch: optional: true - fflate@0.8.2: - resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} - figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -3227,8 +3231,8 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - file-type@21.0.0: - resolution: {integrity: sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==} + file-type@21.3.0: + resolution: {integrity: sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==} engines: {node: '>=20'} fill-range@7.1.1: @@ -3282,12 +3286,12 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.4: - resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} - fs-extra@11.3.2: - resolution: {integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==} + fs-extra@11.3.3: + resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} engines: {node: '>=14.14'} fs.realpath@1.0.0: @@ -3347,23 +3351,23 @@ packages: resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} engines: {node: '>= 14'} - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} hasBin: true - glob@11.0.3: - resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} engines: {node: 20 || >=22} hasBin: true + glob@13.0.0: + resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} + engines: {node: 20 || >=22} + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -3387,9 +3391,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - graphile-config@0.0.1-beta.18: resolution: {integrity: sha512-uMdF9Rt8/NwT1wVXNleYgM5ro2hHDodHiKA3efJhgdU8iP+r/hksnghOHreMva0sF5tV73f4TpiELPUR0g7O9w==} engines: {node: '>=16'} @@ -3399,8 +3400,8 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - graphql-request@7.3.1: - resolution: {integrity: sha512-GdinBsBVYrWzwEvOlzadrV5j8mdOc9ZT8In9QyRIZaxbhkTL08j35yNbPp96jAacYzjeD/hKKy2E2RGI7c7Yug==} + graphql-request@7.4.0: + resolution: {integrity: sha512-xfr+zFb/QYbs4l4ty0dltqiXIp07U6sl+tOKAb0t50/EnQek6CVVBLjETXi+FghElytvgaAWtIOt3EV7zLzIAQ==} peerDependencies: graphql: 14 - 16 @@ -3435,6 +3436,10 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + hashery@1.4.0: + resolution: {integrity: sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ==} + engines: {node: '>=20'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -3445,8 +3450,8 @@ packages: hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - hookified@1.12.2: - resolution: {integrity: sha512-aokUX1VdTpI0DUsndvW+OiwmBpKCu/NgRsSSkuSY0zq8PY6Q6a+lmOfAFDXAAOtBqJELvcWY9L1EVtzjbQcMdg==} + hookified@1.15.0: + resolution: {integrity: sha512-51w+ZZGt7Zw5q7rM3nC4t3aLn/xvKDETsXqMczndvwyVQhAHfUmUuFBRFcos8Iyebtk7OAE9dL26wFNzZVVOkw==} html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -3474,8 +3479,8 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - iconv-lite@0.7.0: - resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} ieee754@1.2.1: @@ -3525,8 +3530,8 @@ packages: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} - ioredis@5.8.2: - resolution: {integrity: sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==} + ioredis@5.9.2: + resolution: {integrity: sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ==} engines: {node: '>=12.22.0'} ip-address@10.1.0: @@ -3838,8 +3843,8 @@ packages: jose@4.15.9: resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} - jose@6.1.1: - resolution: {integrity: sha512-GWSqjfOPf4cWOkBzw5THBjtGPhXKqYnfRBzh4Ni+ArTrQQ9unvmsA3oFLqaYKoKe5sjWmGu5wVKg9Ft1i+LQfg==} + jose@6.1.3: + resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} @@ -3848,12 +3853,12 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true jsesc@3.0.2: @@ -3890,21 +3895,21 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - jsonwebtoken@9.0.2: - resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + jsonwebtoken@9.0.3: + resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} engines: {node: '>=12', npm: '>=6'} - jwa@1.4.2: - resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} - jws@3.2.2: - resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - keyv@5.5.3: - resolution: {integrity: sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==} + keyv@5.6.0: + resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} kysely@0.27.5: resolution: {integrity: sha512-s7hZHcQeSNKpzCkHRm8yA+0JPLjncSWnjb+2TIElwS2JAqYr+Kv3Ess+9KFfJS0C1xcQ1i9NkNHpWwCYpHMWsA==} @@ -3925,12 +3930,12 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - link-preview-js@3.1.0: - resolution: {integrity: sha512-hSvdHCy7tZJ8ohdgN5WcTBKaubpX7saYBzrSmNDDHnC7P6q+F4we+dwXuEr9LuplnkiGxkD4SaO4rrschfCZ2A==} + link-preview-js@3.2.0: + resolution: {integrity: sha512-FvrLltjOPGbTzt+RugbzM7g8XuUNLPO2U/INSLczrYdAA32E7nZVUrVL1gr61DGOArGJA2QkPGMEvNMLLsXREA==} engines: {node: '>=18'} - load-esm@1.0.2: - resolution: {integrity: sha512-nVAvWk/jeyrWyXEAs84mpQCYccxRqgKY4OznLuJhJCa0XsPSfdOIr2zvBZEj3IHEHbX97jjscKRRV539bW0Gpw==} + load-esm@1.0.3: + resolution: {integrity: sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==} engines: {node: '>=13.2.0'} load-tsconfig@0.2.5: @@ -3975,11 +3980,8 @@ packages: lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - lodash.sortby@4.7.0: - resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} @@ -3998,8 +4000,8 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.2.2: - resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + lru-cache@11.2.5: + resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} engines: {node: 20 || >=22} lru-cache@5.1.1: @@ -4037,10 +4039,6 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -4107,8 +4105,8 @@ packages: multipipe@1.0.2: resolution: {integrity: sha512-6uiC9OvY71vzSGX8lZvSqscE7ft9nPupJ8fMjrCNRAUy2LREUW42UL+V/NTrogr6rFgRydUrCX4ZitfpSNkSCQ==} - music-metadata@11.10.0: - resolution: {integrity: sha512-alZYPjpqAPFgVZaFQob0PMq/9tSqaR+3m159vavrptxj09P0GcyBkDQI/wuCyn4uz/TDCrS8gN+9SzURlahmdQ==} + music-metadata@11.11.0: + resolution: {integrity: sha512-OTlsv/FiCr+c4+fC6t9j/GTC/m1KKc3QtOTYHVEvvGLDLpPdtgf32pB7JXJ/Xi8qdIxwwh2PR8J/1t0QL1BxWQ==} engines: {node: '>=18'} mute-stream@0.0.8: @@ -4199,8 +4197,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - oauth4webapi@3.8.2: - resolution: {integrity: sha512-FzZZ+bht5X0FKe7Mwz3DAVAmlH1BV5blSak/lHMBKz0/EBMhX6B10GlQYI51+oRp8ObJaX0g6pXrAxZh5s8rjw==} + oauth4webapi@3.8.3: + resolution: {integrity: sha512-pQ5BsX3QRTgnt5HxgHwgunIRaDXBdkT23tf8dfzmtTIL2LTpdmxgbpbBm0VgFWAIDlezQvQCTgnVIUmHupXHxw==} oauth@0.9.15: resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} @@ -4290,14 +4288,6 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - p-queue@9.0.1: - resolution: {integrity: sha512-RhBdVhSwJb7Ocn3e8ULk4NMwBEuOxe+1zcgphUy9c2e5aR/xbEsdVXxHJ3lynw6Qiqu7OINEyHlZkiblEpaq7w==} - engines: {node: '>=20'} - - p-timeout@7.0.1: - resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==} - engines: {node: '>=20'} - p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -4350,9 +4340,8 @@ packages: resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} engines: {node: 20 || >=22} - path-to-regexp@8.2.0: - resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} - engines: {node: '>=16'} + path-to-regexp@8.3.0: + resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==} path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} @@ -4361,30 +4350,30 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pg-cloudflare@1.2.7: - resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==} + pg-cloudflare@1.3.0: + resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==} - pg-connection-string@2.9.1: - resolution: {integrity: sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==} + pg-connection-string@2.10.1: + resolution: {integrity: sha512-iNzslsoeSH2/gmDDKiyMqF64DATUCWj3YJ0wP14kqcsf2TUklwimd+66yYojKwZCA7h2yRNLGug71hCBA2a4sw==} pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} engines: {node: '>=4.0.0'} - pg-pool@3.10.1: - resolution: {integrity: sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==} + pg-pool@3.11.0: + resolution: {integrity: sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==} peerDependencies: pg: '>=8.0' - pg-protocol@1.10.3: - resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==} + pg-protocol@1.11.0: + resolution: {integrity: sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==} pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} - pg@8.16.3: - resolution: {integrity: sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==} + pg@8.17.2: + resolution: {integrity: sha512-vjbKdiBJRqzcYw1fNU5KuHyYvdJ1qpcQg1CeBrHFqV1pWgHeVR6j/+kX0E1AAXfyuLUGY1ICrN2ELKA/z2HWzw==} engines: {node: '>= 16.0.0'} peerDependencies: pg-native: '>=3.0.1' @@ -4409,15 +4398,18 @@ packages: pino-abstract-transport@2.0.0: resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} - pino-pretty@13.1.2: - resolution: {integrity: sha512-3cN0tCakkT4f3zo9RXDIhy6GTvtYD6bK4CRBLN9j3E/ePqN1tugAXD5rGVfoChW6s0hiek+eyYlLNqc/BG7vBQ==} + pino-abstract-transport@3.0.0: + resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + + pino-pretty@13.1.3: + resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==} hasBin: true - pino-std-serializers@7.0.0: - resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} - pino@10.1.0: - resolution: {integrity: sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==} + pino@10.3.0: + resolution: {integrity: sha512-0GNPNzHXBKw6U/InGe79A3Crzyk9bcSyObF9/Gfo9DLEf5qj5RF50RSjsu0W1rZ6ZqRGdzDFCRBQvi9/rSGPtA==} hasBin: true pino@9.14.0: @@ -4469,8 +4461,8 @@ packages: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} - postgres-bytea@1.0.0: - resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + postgres-bytea@1.0.1: + resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} engines: {node: '>=0.10.0'} postgres-date@1.0.7: @@ -4494,8 +4486,8 @@ packages: preact@10.24.3: resolution: {integrity: sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==} - preact@10.27.2: - resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} + preact@10.28.2: + resolution: {integrity: sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -4545,15 +4537,15 @@ packages: pure-rand@7.0.1: resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} - qified@0.5.1: - resolution: {integrity: sha512-+BtFN3dCP+IaFA6IYNOu/f/uK1B8xD2QWyOeCse0rjtAebBmkzgd2d1OAXi3ikAzJMIBSdzZDNZ3wZKEUDQs5w==} + qified@0.6.0: + resolution: {integrity: sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==} engines: {node: '>=20'} qr.js@0.0.0: resolution: {integrity: sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==} - qs@6.14.0: - resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + qs@6.14.1: + resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} engines: {node: '>=0.6'} querystring@0.2.0: @@ -4561,9 +4553,6 @@ packages: engines: {node: '>=0.4.x'} deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} @@ -4588,8 +4577,8 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-is@19.2.0: - resolution: {integrity: sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==} + react-is@19.2.4: + resolution: {integrity: sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==} react-polyglot@0.7.2: resolution: {integrity: sha512-d/075aofJ4of9wOSBewl+ViFkkM0L1DgE3RVDOXrHZ92w4o2643sTQJ6lSPw8wsJWFmlB/3Pvwm0UbGNvLfPBw==} @@ -4657,8 +4646,8 @@ packages: resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true - remeda@2.32.0: - resolution: {integrity: sha512-BZx9DsT4FAgXDTOdgJIc5eY6ECIXMwtlSPQoPglF20ycSWigttDDe88AozEsPPT4OWk5NujroGSBC1phw5uU+w==} + remeda@2.33.4: + resolution: {integrity: sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==} require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} @@ -4691,12 +4680,8 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rollup@4.53.1: - resolution: {integrity: sha512-n2I0V0lN3E9cxxMqBCT3opWOiQBzRN7UG60z/WDKqdX2zHUS/39lezBcsckZFsV6fUTSnfqI7kHf60jDAPGKug==} + rollup@4.57.0: + resolution: {integrity: sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -4704,9 +4689,6 @@ packages: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} @@ -4740,6 +4722,7 @@ packages: scmp@2.1.0: resolution: {integrity: sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==} + deprecated: Just use Node.js's crypto.timingSafeEqual() secure-json-parse@4.1.0: resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} @@ -4838,10 +4821,9 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - source-map@0.8.0-beta.0: - resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} - engines: {node: '>= 8'} - deprecated: The work that was done in this beta branch won't be included in future versions + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} @@ -4946,8 +4928,8 @@ packages: stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true @@ -4963,8 +4945,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - synckit@0.11.11: - resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + synckit@0.11.12: + resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} engines: {node: ^14.18.0 || >=16.0.0} test-exclude@6.0.0: @@ -4981,6 +4963,10 @@ packages: thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + thread-stream@4.0.0: + resolution: {integrity: sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==} + engines: {node: '>=20'} + through2@0.4.2: resolution: {integrity: sha512-45Llu+EwHKtAZYTPPVn3XZHBgakWMN3rokhEv5hu596XP+cNgplMg+Gj+1nmAvj+L0K7+N49zBKx5rah5u0QIQ==} @@ -5001,22 +4987,19 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - token-types@6.1.1: - resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==} + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} engines: {node: '>=14.16'} tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tr46@1.0.1: - resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + ts-api-utils@2.4.0: + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -5044,8 +5027,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsup@8.5.0: - resolution: {integrity: sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==} + tsup@8.5.1: + resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -5063,47 +5046,47 @@ packages: typescript: optional: true - tsx@4.20.6: - resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} engines: {node: '>=18.0.0'} hasBin: true - turbo-darwin-64@2.6.0: - resolution: {integrity: sha512-6vHnLAubHj8Ib45Knu+oY0ZVCLO7WcibzAvt5b1E72YHqAs4y8meMAGMZM0jLqWPh/9maHDc16/qBCMxtW4pXg==} + turbo-darwin-64@2.7.6: + resolution: {integrity: sha512-bYu0qnWju2Ha3EbIkPCk1SMLT3sltKh1P/Jy5FER6BmH++H5z+T5MHh3W1Xoers9rk4N1VdKvog9FO1pxQyjhw==} cpu: [x64] os: [darwin] - turbo-darwin-arm64@2.6.0: - resolution: {integrity: sha512-IU+gWMEXNBw8H0pxvE7nPEa5p6yahxbN8g/Q4Bf0AHymsAFqsScgV0peeNbWybdmY9jk1LPbALOsF2kY1I7ZiQ==} + turbo-darwin-arm64@2.7.6: + resolution: {integrity: sha512-KCxTf3Y1hgNLYIWRLw8bwH8Zie9RyCGoxAlXYsCBI/YNqBSR+ZZK9KYzFxAqDaVaNvTwLFv3rJRGsXOFWg4+Uw==} cpu: [arm64] os: [darwin] - turbo-linux-64@2.6.0: - resolution: {integrity: sha512-CKoiJ2ZFJLCDsWdRlZg+ew1BkGn8iCEGdePhISVpjsGwkJwSVhVu49z2zKdBeL1IhcSKS2YALwp9ellNZANJxw==} + turbo-linux-64@2.7.6: + resolution: {integrity: sha512-vjoU8zIfNgvJR3cMitgw7inEoi6bmuVuFawDl5yKtxjAEhDktFdRBpGS3WojD4l3BklBbIK689ssXcGf21LxRA==} cpu: [x64] os: [linux] - turbo-linux-arm64@2.6.0: - resolution: {integrity: sha512-WroVCdCvJbrhNxNdw7XB7wHAfPPJPV+IXY+ZKNed+9VdfBu/2mQNfKnvqTuFTH7n+Pdpv8to9qwhXRTJe26upg==} + turbo-linux-arm64@2.7.6: + resolution: {integrity: sha512-TcMpBvTqZf+1DptrVYLbZls7WY1UVNDTGaf0bo7/GCgWYv5eZHCVo4Td7kCJeDU4glbXg67REX0md0S0V6ghMg==} cpu: [arm64] os: [linux] - turbo-windows-64@2.6.0: - resolution: {integrity: sha512-7pZo5aGQPR+A7RMtWCZHusarJ6y15LQ+o3jOmpMxTic/W6Bad+jSeqo07TWNIseIWjCVzrSv27+0odiYRYtQdA==} + turbo-windows-64@2.7.6: + resolution: {integrity: sha512-1/MhkYldiihjneY8QnnDMbAkHXn/udTWSVYS94EMlkE9AShozsLTTOT1gDOpX06EfEW5njP09suhMvxbvwuwpQ==} cpu: [x64] os: [win32] - turbo-windows-arm64@2.6.0: - resolution: {integrity: sha512-1Ty+NwIksQY7AtFUCPrTpcKQE7zmd/f7aRjdT+qkqGFQjIjFYctEtN7qo4vpQPBgCfS1U3ka83A2u/9CfJQ3wQ==} + turbo-windows-arm64@2.7.6: + resolution: {integrity: sha512-0wDVnUJLFAWm4ZzOQFDkbyyUqaszorTGf3Rdc22IRIyJTTLd6ajqdb+cWD89UZ1RKr953+PZR1gqgWQY4PDuhA==} cpu: [arm64] os: [win32] - turbo@2.6.0: - resolution: {integrity: sha512-kC5VJqOXo50k0/0jnJDDjibLAXalqT9j7PQ56so0pN+81VR4Fwb2QgIE9dTzT3phqOTQuEXkPh3sCpnv5Isz2g==} + turbo@2.7.6: + resolution: {integrity: sha512-PO9AvJLEsNLO+EYhF4zB+v10hOjsJe5kJW+S6tTbRv+TW7gf1Qer4mfjP9h3/y9h8ZiPvOrenxnEgDtFgaM5zw==} hasBin: true - twilio@5.10.4: - resolution: {integrity: sha512-5dUsT3/O1+WxyJop2a6a4r92NAgtEQL7+oSU4t466NPhDaPOOBH/uomxnYHD5GWouYo7CZ/B7XSOwlhEUAHpWg==} + twilio@5.12.0: + resolution: {integrity: sha512-ZAKnDKcWvJSb90xQS13QB5KQOeMJPzsRPHxZqju8i5ALg3D4hNwAF9bpytVTxTJV99BL4Rn6Un+ZtXjGeMpjvQ==} engines: {node: '>=14.0'} type-check@0.4.0: @@ -5118,10 +5101,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@4.41.0: - resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} - engines: {node: '>=16'} - typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -5143,8 +5122,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - ufo@1.6.1: - resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + ufo@1.6.3: + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} uid@2.0.2: resolution: {integrity: sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==} @@ -5174,8 +5153,8 @@ packages: unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - update-browserslist-db@1.1.4: - resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -5217,15 +5196,9 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - webidl-conversions@4.0.2: - resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - whatwg-url@7.1.0: - resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -5238,8 +5211,8 @@ packages: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - which-typed-array@1.1.19: - resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + which-typed-array@1.1.20: + resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} engines: {node: '>= 0.4'} which@1.3.1: @@ -5251,6 +5224,9 @@ packages: engines: {node: '>= 8'} hasBin: true + win-guid@0.2.0: + resolution: {integrity: sha512-iekGhWzFQSunvE87ndXxoa6UgyQbkL4MmbYTFhQnk94pVsAW89mWnvW1zI3JMnypUm8jykJaITudspoR8NrRBQ==} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -5274,8 +5250,8 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -5333,11 +5309,13 @@ packages: snapshots: + '@adiwajshing/keyed-db@0.2.4': {} + '@auth/core@0.41.1': dependencies: '@panva/hkdf': 1.2.1 - jose: 6.1.1 - oauth4webapi: 3.8.2 + jose: 6.1.3 + oauth4webapi: 3.8.3 preact: 10.24.3 preact-render-to-string: 6.5.11(preact@10.24.3) @@ -5350,25 +5328,25 @@ snapshots: - '@simplewebauthn/server' - nodemailer - '@babel/code-frame@7.27.1': + '@babel/code-frame@7.28.6': dependencies: '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.28.5': {} + '@babel/compat-data@7.28.6': {} - '@babel/core@7.28.5': + '@babel/core@7.28.6': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) - '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/code-frame': 7.28.6 + '@babel/generator': 7.28.6 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) + '@babel/helpers': 7.28.6 + '@babel/parser': 7.28.6 + '@babel/template': 7.28.6 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -5378,49 +5356,49 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/eslint-parser@7.28.4(@babel/core@7.28.5)(eslint@9.39.1)': + '@babel/eslint-parser@7.28.4(@babel/core@7.28.6)(eslint@9.39.2)': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 9.39.1 + eslint: 9.39.2 eslint-visitor-keys: 2.1.0 semver: 6.3.1 - '@babel/generator@7.28.5': + '@babel/generator@7.28.6': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.27.2': + '@babel/helper-compilation-targets@7.28.6': dependencies: - '@babel/compat-data': 7.28.5 + '@babel/compat-data': 7.28.6 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.27.0 + browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 '@babel/helper-globals@7.28.0': {} - '@babel/helper-module-imports@7.27.1': + '@babel/helper-module-imports@7.28.6': dependencies: - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-module-imports': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-module-imports': 7.28.6 '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/traverse': 7.28.6 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.27.1': {} + '@babel/helper-plugin-utils@7.28.6': {} '@babel/helper-string-parser@7.27.1': {} @@ -5428,151 +5406,146 @@ snapshots: '@babel/helper-validator-option@7.27.1': {} - '@babel/helpers@7.28.4': + '@babel/helpers@7.28.6': dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/template': 7.28.6 + '@babel/types': 7.28.6 - '@babel/parser@7.28.5': + '@babel/parser@7.28.6': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.5)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.5)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.5)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.5)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.5)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.5)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.5)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.5)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.5)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.5)': + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.28.6)': dependencies: - '@babel/core': 7.28.5 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 - '@babel/runtime@7.28.4': {} + '@babel/runtime@7.28.6': {} - '@babel/template@7.27.2': + '@babel/template@7.28.6': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/code-frame': 7.28.6 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 - '@babel/traverse@7.28.5': + '@babel/traverse@7.28.6': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 + '@babel/code-frame': 7.28.6 + '@babel/generator': 7.28.6 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/template': 7.28.6 + '@babel/types': 7.28.6 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.28.5': + '@babel/types@7.28.6': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 '@bcoe/v8-coverage@0.2.3': {} - '@borewit/text-codec@0.1.1': {} + '@borewit/text-codec@0.2.1': {} - '@borewit/text-codec@0.2.0': {} - - '@cacheable/memoize@2.0.3': + '@cacheable/memory@2.0.7': dependencies: - '@cacheable/utils': 2.2.0 + '@cacheable/utils': 2.3.3 + '@keyv/bigmap': 1.3.1(keyv@5.6.0) + hookified: 1.15.0 + keyv: 5.6.0 - '@cacheable/memory@2.0.4': + '@cacheable/node-cache@1.7.6': dependencies: - '@cacheable/utils': 2.2.0 - '@keyv/bigmap': 1.1.0(keyv@5.5.3) - hookified: 1.12.2 - keyv: 5.5.3 + cacheable: 2.3.2 + hookified: 1.15.0 + keyv: 5.6.0 - '@cacheable/node-cache@1.7.4': + '@cacheable/utils@2.3.3': dependencies: - cacheable: 2.1.1 - hookified: 1.12.2 - keyv: 5.5.3 - - '@cacheable/utils@2.2.0': - dependencies: - keyv: 5.5.3 + hashery: 1.4.0 + keyv: 5.6.0 '@chatscope/chat-ui-kit-react@2.1.1(prop-types@15.8.1)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: @@ -5592,13 +5565,13 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@emnapi/core@1.7.0': + '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.7.0': + '@emnapi/runtime@1.8.1': dependencies: tslib: 2.8.1 optional: true @@ -5610,8 +5583,8 @@ snapshots: '@emotion/babel-plugin@11.13.5': dependencies: - '@babel/helper-module-imports': 7.27.1 - '@babel/runtime': 7.28.4 + '@babel/helper-module-imports': 7.28.6 + '@babel/runtime': 7.28.6 '@emotion/hash': 0.9.2 '@emotion/memoize': 0.9.0 '@emotion/serialize': 1.3.3 @@ -5642,7 +5615,7 @@ snapshots: '@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@emotion/babel-plugin': 11.13.5 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 @@ -5662,7 +5635,7 @@ snapshots: '@emotion/memoize': 0.9.0 '@emotion/unitless': 0.10.0 '@emotion/utils': 1.4.2 - csstype: 3.1.3 + csstype: 3.2.3 '@emotion/server@11.11.0': dependencies: @@ -5675,7 +5648,7 @@ snapshots: '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.4.0 '@emotion/react': 11.14.0(@types/react@19.2.2)(react@19.2.0) @@ -5698,87 +5671,87 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.25.12': + '@esbuild/aix-ppc64@0.27.2': optional: true - '@esbuild/android-arm64@0.25.12': + '@esbuild/android-arm64@0.27.2': optional: true - '@esbuild/android-arm@0.25.12': + '@esbuild/android-arm@0.27.2': optional: true - '@esbuild/android-x64@0.25.12': + '@esbuild/android-x64@0.27.2': optional: true - '@esbuild/darwin-arm64@0.25.12': + '@esbuild/darwin-arm64@0.27.2': optional: true - '@esbuild/darwin-x64@0.25.12': + '@esbuild/darwin-x64@0.27.2': optional: true - '@esbuild/freebsd-arm64@0.25.12': + '@esbuild/freebsd-arm64@0.27.2': optional: true - '@esbuild/freebsd-x64@0.25.12': + '@esbuild/freebsd-x64@0.27.2': optional: true - '@esbuild/linux-arm64@0.25.12': + '@esbuild/linux-arm64@0.27.2': optional: true - '@esbuild/linux-arm@0.25.12': + '@esbuild/linux-arm@0.27.2': optional: true - '@esbuild/linux-ia32@0.25.12': + '@esbuild/linux-ia32@0.27.2': optional: true - '@esbuild/linux-loong64@0.25.12': + '@esbuild/linux-loong64@0.27.2': optional: true - '@esbuild/linux-mips64el@0.25.12': + '@esbuild/linux-mips64el@0.27.2': optional: true - '@esbuild/linux-ppc64@0.25.12': + '@esbuild/linux-ppc64@0.27.2': optional: true - '@esbuild/linux-riscv64@0.25.12': + '@esbuild/linux-riscv64@0.27.2': optional: true - '@esbuild/linux-s390x@0.25.12': + '@esbuild/linux-s390x@0.27.2': optional: true - '@esbuild/linux-x64@0.25.12': + '@esbuild/linux-x64@0.27.2': optional: true - '@esbuild/netbsd-arm64@0.25.12': + '@esbuild/netbsd-arm64@0.27.2': optional: true - '@esbuild/netbsd-x64@0.25.12': + '@esbuild/netbsd-x64@0.27.2': optional: true - '@esbuild/openbsd-arm64@0.25.12': + '@esbuild/openbsd-arm64@0.27.2': optional: true - '@esbuild/openbsd-x64@0.25.12': + '@esbuild/openbsd-x64@0.27.2': optional: true - '@esbuild/openharmony-arm64@0.25.12': + '@esbuild/openharmony-arm64@0.27.2': optional: true - '@esbuild/sunos-x64@0.25.12': + '@esbuild/sunos-x64@0.27.2': optional: true - '@esbuild/win32-arm64@0.25.12': + '@esbuild/win32-arm64@0.27.2': optional: true - '@esbuild/win32-ia32@0.25.12': + '@esbuild/win32-ia32@0.27.2': optional: true - '@esbuild/win32-x64@0.25.12': + '@esbuild/win32-x64@0.27.2': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2)': dependencies: - eslint: 9.39.1 + eslint: 9.39.2 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -5803,7 +5776,7 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.1': + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6 debug: 4.4.3 @@ -5811,13 +5784,13 @@ snapshots: globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.0 + js-yaml: 4.1.1 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@9.39.1': {} + '@eslint/js@9.39.2': {} '@eslint/object-schema@2.1.7': {} @@ -5904,7 +5877,7 @@ snapshots: dependencies: '@hapi/boom': 10.0.1 - '@hapi/cryptiles@6.0.1': + '@hapi/cryptiles@6.0.3': dependencies: '@hapi/boom': 10.0.1 @@ -5946,7 +5919,7 @@ snapshots: '@hapi/b64': 6.0.1 '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 - '@hapi/cryptiles': 6.0.1 + '@hapi/cryptiles': 6.0.3 '@hapi/hoek': 11.0.7 '@hapi/mimos@7.0.1': @@ -5988,7 +5961,7 @@ snapshots: '@hapi/boom': 10.0.1 '@hapi/bounce': 3.0.2 '@hapi/bourne': 3.0.0 - '@hapi/cryptiles': 6.0.1 + '@hapi/cryptiles': 6.0.3 '@hapi/hoek': 11.0.7 '@hapi/iron': 7.0.1 '@hapi/validate': 2.0.1 @@ -6129,7 +6102,7 @@ snapshots: '@img/sharp-wasm32@0.34.5': dependencies: - '@emnapi/runtime': 1.7.0 + '@emnapi/runtime': 1.8.1 optional: true '@img/sharp-win32-arm64@0.34.5': @@ -6141,14 +6114,14 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true - '@inquirer/external-editor@1.0.3(@types/node@24.10.0)': + '@inquirer/external-editor@1.0.3(@types/node@24.10.9)': dependencies: chardet: 2.1.1 - iconv-lite: 0.7.0 + iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.9 - '@ioredis/commands@1.4.0': {} + '@ioredis/commands@1.5.0': {} '@isaacs/balanced-match@4.0.1': {} @@ -6170,7 +6143,7 @@ snapshots: camelcase: 5.3.1 find-up: 4.1.0 get-package-type: 0.1.0 - js-yaml: 3.14.1 + js-yaml: 3.14.2 resolve-from: 5.0.0 '@istanbuljs/schema@0.1.3': {} @@ -6178,13 +6151,13 @@ snapshots: '@jest/console@30.2.0': dependencies: '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 chalk: 4.1.2 jest-message-util: 30.2.0 jest-util: 30.2.0 slash: 3.0.0 - '@jest/core@30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3))': + '@jest/core@30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3))': dependencies: '@jest/console': 30.2.0 '@jest/pattern': 30.0.1 @@ -6192,14 +6165,14 @@ snapshots: '@jest/test-result': 30.2.0 '@jest/transform': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 4.3.1 exit-x: 0.2.2 graceful-fs: 4.2.11 jest-changed-files: 30.2.0 - jest-config: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) + jest-config: 30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)) jest-haste-map: 30.2.0 jest-message-util: 30.2.0 jest-regex-util: 30.0.1 @@ -6226,7 +6199,7 @@ snapshots: dependencies: '@jest/fake-timers': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 jest-mock: 30.2.0 '@jest/expect-utils@30.2.0': @@ -6244,7 +6217,7 @@ snapshots: dependencies: '@jest/types': 30.2.0 '@sinonjs/fake-timers': 13.0.5 - '@types/node': 24.10.0 + '@types/node': 24.10.9 jest-message-util: 30.2.0 jest-mock: 30.2.0 jest-util: 30.2.0 @@ -6262,7 +6235,7 @@ snapshots: '@jest/pattern@30.0.1': dependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.9 jest-regex-util: 30.0.1 '@jest/reporters@30.2.0': @@ -6273,11 +6246,11 @@ snapshots: '@jest/transform': 30.2.0 '@jest/types': 30.2.0 '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 24.10.0 + '@types/node': 24.10.9 chalk: 4.1.2 collect-v8-coverage: 1.0.3 exit-x: 0.2.2 - glob: 10.4.5 + glob: 10.5.0 graceful-fs: 4.2.11 istanbul-lib-coverage: 3.2.2 istanbul-lib-instrument: 6.0.3 @@ -6295,7 +6268,7 @@ snapshots: '@jest/schemas@30.0.5': dependencies: - '@sinclair/typebox': 0.34.41 + '@sinclair/typebox': 0.34.48 '@jest/snapshot-utils@30.2.0': dependencies: @@ -6326,7 +6299,7 @@ snapshots: '@jest/transform@30.2.0': dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@jest/types': 30.2.0 '@jridgewell/trace-mapping': 0.3.31 babel-plugin-istanbul: 7.0.1 @@ -6350,8 +6323,8 @@ snapshots: '@jest/schemas': 30.0.5 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 24.10.0 - '@types/yargs': 17.0.34 + '@types/node': 24.10.9 + '@types/yargs': 17.0.35 chalk: 4.1.2 '@jridgewell/gen-mapping@0.3.13': @@ -6378,10 +6351,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@keyv/bigmap@1.1.0(keyv@5.5.3)': + '@keyv/bigmap@1.3.1(keyv@5.6.0)': dependencies: - hookified: 1.12.2 - keyv: 5.5.3 + hashery: 1.4.0 + hookified: 1.15.0 + keyv: 5.6.0 '@keyv/serialize@1.1.1': {} @@ -6391,7 +6365,7 @@ snapshots: '@mui/icons-material@6.5.0(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 optionalDependencies: @@ -6399,7 +6373,7 @@ snapshots: '@mui/material-nextjs@6.5.0(@emotion/cache@11.14.0)(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/server@11.11.0)(@types/react@19.2.2)(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@emotion/react': 11.14.0(@types/react@19.2.2)(react@19.2.0) next: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 @@ -6410,7 +6384,7 @@ snapshots: '@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/core-downloads-tracker': 6.5.0 '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) '@mui/types': 7.2.24(@types/react@19.2.2) @@ -6418,11 +6392,11 @@ snapshots: '@popperjs/core': 2.11.8 '@types/react-transition-group': 4.4.12(@types/react@19.2.2) clsx: 2.1.1 - csstype: 3.1.3 + csstype: 3.2.3 prop-types: 15.8.1 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - react-is: 19.2.0 + react-is: 19.2.4 react-transition-group: 4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0) optionalDependencies: '@emotion/react': 11.14.0(@types/react@19.2.2)(react@19.2.0) @@ -6431,7 +6405,7 @@ snapshots: '@mui/private-theming@6.4.9(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/utils': 6.4.9(@types/react@19.2.2)(react@19.2.0) prop-types: 15.8.1 react: 19.2.0 @@ -6440,11 +6414,11 @@ snapshots: '@mui/styled-engine@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@emotion/cache': 11.14.0 '@emotion/serialize': 1.3.3 '@emotion/sheet': 1.4.0 - csstype: 3.1.3 + csstype: 3.2.3 prop-types: 15.8.1 react: 19.2.0 optionalDependencies: @@ -6453,13 +6427,13 @@ snapshots: '@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/private-theming': 6.4.9(@types/react@19.2.2)(react@19.2.0) '@mui/styled-engine': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(react@19.2.0) '@mui/types': 7.2.24(@types/react@19.2.2) '@mui/utils': 6.4.9(@types/react@19.2.2)(react@19.2.0) clsx: 2.1.1 - csstype: 3.1.3 + csstype: 3.2.3 prop-types: 15.8.1 react: 19.2.0 optionalDependencies: @@ -6471,43 +6445,43 @@ snapshots: optionalDependencies: '@types/react': 19.2.2 - '@mui/types@7.4.8(@types/react@19.2.2)': + '@mui/types@7.4.10(@types/react@19.2.2)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 optionalDependencies: '@types/react': 19.2.2 '@mui/utils@6.4.9(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/types': 7.2.24(@types/react@19.2.2) '@types/prop-types': 15.7.15 clsx: 2.1.1 prop-types: 15.8.1 react: 19.2.0 - react-is: 19.2.0 + react-is: 19.2.4 optionalDependencies: '@types/react': 19.2.2 - '@mui/utils@7.3.5(@types/react@19.2.2)(react@19.2.0)': + '@mui/utils@7.3.7(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 - '@mui/types': 7.4.8(@types/react@19.2.2) + '@babel/runtime': 7.28.6 + '@mui/types': 7.4.10(@types/react@19.2.2) '@types/prop-types': 15.7.15 clsx: 2.1.1 prop-types: 15.8.1 react: 19.2.0 - react-is: 19.2.0 + react-is: 19.2.4 optionalDependencies: '@types/react': 19.2.2 - '@mui/x-data-grid-pro@7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@mui/x-data-grid-pro@7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) - '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) - '@mui/x-data-grid': 7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@mui/utils': 7.3.7(@types/react@19.2.2)(react@19.2.0) + '@mui/x-data-grid': 7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) '@mui/x-license': 7.29.1(@types/react@19.2.2)(react@19.2.0) '@types/format-util': 1.0.4 @@ -6522,12 +6496,12 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@mui/x-data-grid@7.29.9(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@mui/x-data-grid@7.29.12(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) - '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) + '@mui/utils': 7.3.7(@types/react@19.2.2)(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) clsx: 2.1.1 prop-types: 15.8.1 @@ -6543,10 +6517,10 @@ snapshots: '@mui/x-date-pickers-pro@7.29.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(date-fns@4.1.0)(dayjs@1.11.19)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) - '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) + '@mui/utils': 7.3.7(@types/react@19.2.2)(react@19.2.0) '@mui/x-date-pickers': 7.29.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(date-fns@4.1.0)(dayjs@1.11.19)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) '@mui/x-license': 7.29.1(@types/react@19.2.2)(react@19.2.0) @@ -6565,10 +6539,10 @@ snapshots: '@mui/x-date-pickers@7.29.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@mui/material@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@mui/system@6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(date-fns@4.1.0)(dayjs@1.11.19)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@mui/material': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@mui/system': 6.5.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0))(@types/react@19.2.2)(react@19.2.0) - '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) + '@mui/utils': 7.3.7(@types/react@19.2.2)(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) '@types/react-transition-group': 4.4.12(@types/react@19.2.2) clsx: 2.1.1 @@ -6586,16 +6560,16 @@ snapshots: '@mui/x-internals@7.29.0(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 - '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) + '@babel/runtime': 7.28.6 + '@mui/utils': 7.3.7(@types/react@19.2.2)(react@19.2.0) react: 19.2.0 transitivePeerDependencies: - '@types/react' '@mui/x-license@7.29.1(@types/react@19.2.2)(react@19.2.0)': dependencies: - '@babel/runtime': 7.28.4 - '@mui/utils': 7.3.5(@types/react@19.2.2)(react@19.2.0) + '@babel/runtime': 7.28.6 + '@mui/utils': 7.3.7(@types/react@19.2.2)(react@19.2.0) '@mui/x-internals': 7.29.0(@types/react@19.2.2)(react@19.2.0) react: 19.2.0 transitivePeerDependencies: @@ -6603,22 +6577,22 @@ snapshots: '@napi-rs/wasm-runtime@0.2.12': dependencies: - '@emnapi/core': 1.7.0 - '@emnapi/runtime': 1.7.0 + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.8.1 '@tybys/wasm-util': 0.10.1 optional: true - '@nestjs/axios@4.0.1(@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.12.2)(rxjs@7.8.2)': + '@nestjs/axios@4.0.1(@nestjs/common@11.1.12(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.13.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2) - axios: 1.12.2 + '@nestjs/common': 11.1.12(reflect-metadata@0.2.2)(rxjs@7.8.2) + axios: 1.13.2 rxjs: 7.8.2 - '@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/common@11.1.12(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - file-type: 21.0.0 + file-type: 21.3.0 iterare: 1.2.1 - load-esm: 1.0.2 + load-esm: 1.0.3 reflect-metadata: 0.2.2 rxjs: 7.8.2 tslib: 2.8.1 @@ -6626,13 +6600,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@nestjs/core@11.1.6(@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/core@11.1.12(@nestjs/common@11.1.12(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.12(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nuxt/opencollective': 0.4.1 fast-safe-stringify: 2.1.1 iterare: 1.2.1 - path-to-regexp: 8.2.0 + path-to-regexp: 8.3.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 tslib: 2.8.1 @@ -6668,18 +6642,6 @@ snapshots: dependencies: eslint-scope: 5.1.1 - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.1 - '@nuxt/opencollective@0.4.1': dependencies: consola: 3.4.2 @@ -6692,21 +6654,21 @@ snapshots: transitivePeerDependencies: - encoding - '@openapitools/openapi-generator-cli@2.25.0(@types/node@24.10.0)': + '@openapitools/openapi-generator-cli@2.28.0(@types/node@24.10.9)': dependencies: - '@nestjs/axios': 4.0.1(@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.12.2)(rxjs@7.8.2) - '@nestjs/common': 11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/axios': 4.0.1(@nestjs/common@11.1.12(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.13.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.12(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.12(@nestjs/common@11.1.12(reflect-metadata@0.2.2)(rxjs@7.8.2))(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nuxtjs/opencollective': 0.3.2 - axios: 1.12.2 + axios: 1.13.2 chalk: 4.1.2 commander: 8.3.0 compare-versions: 6.1.1 concurrently: 9.2.1 console.table: 0.10.0 - fs-extra: 11.3.2 - glob: 11.0.3 - inquirer: 8.2.7(@types/node@24.10.0) + fs-extra: 11.3.3 + glob: 13.0.0 + inquirer: 8.2.7(@types/node@24.10.9) proxy-agent: 6.5.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 @@ -6756,77 +6718,86 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@rollup/rollup-android-arm-eabi@4.53.1': + '@rollup/rollup-android-arm-eabi@4.57.0': optional: true - '@rollup/rollup-android-arm64@4.53.1': + '@rollup/rollup-android-arm64@4.57.0': optional: true - '@rollup/rollup-darwin-arm64@4.53.1': + '@rollup/rollup-darwin-arm64@4.57.0': optional: true - '@rollup/rollup-darwin-x64@4.53.1': + '@rollup/rollup-darwin-x64@4.57.0': optional: true - '@rollup/rollup-freebsd-arm64@4.53.1': + '@rollup/rollup-freebsd-arm64@4.57.0': optional: true - '@rollup/rollup-freebsd-x64@4.53.1': + '@rollup/rollup-freebsd-x64@4.57.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.53.1': + '@rollup/rollup-linux-arm-gnueabihf@4.57.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.53.1': + '@rollup/rollup-linux-arm-musleabihf@4.57.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.53.1': + '@rollup/rollup-linux-arm64-gnu@4.57.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.53.1': + '@rollup/rollup-linux-arm64-musl@4.57.0': optional: true - '@rollup/rollup-linux-loong64-gnu@4.53.1': + '@rollup/rollup-linux-loong64-gnu@4.57.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.53.1': + '@rollup/rollup-linux-loong64-musl@4.57.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.53.1': + '@rollup/rollup-linux-ppc64-gnu@4.57.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.53.1': + '@rollup/rollup-linux-ppc64-musl@4.57.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.53.1': + '@rollup/rollup-linux-riscv64-gnu@4.57.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.53.1': + '@rollup/rollup-linux-riscv64-musl@4.57.0': optional: true - '@rollup/rollup-linux-x64-musl@4.53.1': + '@rollup/rollup-linux-s390x-gnu@4.57.0': optional: true - '@rollup/rollup-openharmony-arm64@4.53.1': + '@rollup/rollup-linux-x64-gnu@4.57.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.53.1': + '@rollup/rollup-linux-x64-musl@4.57.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.53.1': + '@rollup/rollup-openbsd-x64@4.57.0': optional: true - '@rollup/rollup-win32-x64-gnu@4.53.1': + '@rollup/rollup-openharmony-arm64@4.57.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.53.1': + '@rollup/rollup-win32-arm64-msvc@4.57.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.57.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.57.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.57.0': optional: true '@rtsao/scc@1.1.0': {} - '@rushstack/eslint-patch@1.14.1': {} + '@rushstack/eslint-patch@1.15.0': {} - '@sinclair/typebox@0.34.41': {} + '@sinclair/typebox@0.34.48': {} '@sinonjs/commons@3.0.1': dependencies: @@ -6840,11 +6811,10 @@ snapshots: dependencies: tslib: 2.8.1 - '@tokenizer/inflate@0.2.7': + '@tokenizer/inflate@0.4.1': dependencies: debug: 4.4.3 - fflate: 0.8.2 - token-types: 6.1.1 + token-types: 6.1.2 transitivePeerDependencies: - supports-color @@ -6852,7 +6822,7 @@ snapshots: '@tootallnate/quickjs-emscripten@0.23.0': {} - '@tsconfig/node10@1.0.11': {} + '@tsconfig/node10@1.0.12': {} '@tsconfig/node12@1.0.11': {} @@ -6867,24 +6837,24 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.28.5 + '@babel/types': 7.28.6 '@types/debug@4.1.12': dependencies: @@ -6894,7 +6864,7 @@ snapshots: '@types/fluent-ffmpeg@2.1.28': dependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.9 '@types/format-util@1.0.4': {} @@ -6903,9 +6873,9 @@ snapshots: '@types/react': 19.2.2 hoist-non-react-statics: 3.3.2 - '@types/interpret@1.1.3': + '@types/interpret@1.1.4': dependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.9 '@types/istanbul-lib-coverage@2.0.6': {} @@ -6928,24 +6898,28 @@ snapshots: '@types/long@4.0.2': {} + '@types/long@5.0.0': + dependencies: + long: 5.3.2 + '@types/ms@2.1.0': {} '@types/node@10.17.60': {} - '@types/node@22.19.0': + '@types/node@22.19.7': dependencies: undici-types: 6.21.0 - '@types/node@24.10.0': + '@types/node@24.10.9': dependencies: undici-types: 7.16.0 '@types/parse-json@4.0.2': {} - '@types/pg@8.15.6': + '@types/pg@8.16.0': dependencies: - '@types/node': 24.10.0 - pg-protocol: 1.10.3 + '@types/node': 24.10.9 + pg-protocol: 1.11.0 pg-types: 2.2.0 '@types/prop-types@15.7.15': {} @@ -6960,7 +6934,7 @@ snapshots: '@types/react@19.2.2': dependencies: - csstype: 3.1.3 + csstype: 3.2.3 '@types/semver@7.7.1': {} @@ -6968,101 +6942,99 @@ snapshots: '@types/yargs-parser@21.0.3': {} - '@types/yargs@17.0.34': + '@types/yargs@17.0.35': dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.46.3(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.46.3 - '@typescript-eslint/type-utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.3 - eslint: 9.39.1 - graphemer: 1.4.0 + '@typescript-eslint/parser': 8.54.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.54.0 + '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.54.0 + eslint: 9.39.2 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.3) + ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.46.3 - '@typescript-eslint/types': 8.46.3 - '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.3 + '@typescript-eslint/scope-manager': 8.54.0 + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.54.0 debug: 4.4.3 - eslint: 9.39.1 + eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.46.3(typescript@5.9.3)': + '@typescript-eslint/project-service@8.54.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.9.3) - '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) + '@typescript-eslint/types': 8.54.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.46.3': + '@typescript-eslint/scope-manager@8.54.0': dependencies: - '@typescript-eslint/types': 8.46.3 - '@typescript-eslint/visitor-keys': 8.46.3 + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/visitor-keys': 8.54.0 - '@typescript-eslint/tsconfig-utils@8.46.3(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.54.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.46.3(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.46.3 - '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2)(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.1 - ts-api-utils: 2.1.0(typescript@5.9.3) + eslint: 9.39.2 + ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.46.3': {} + '@typescript-eslint/types@8.54.0': {} - '@typescript-eslint/typescript-estree@8.46.3(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.54.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.46.3(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.46.3(typescript@5.9.3) - '@typescript-eslint/types': 8.46.3 - '@typescript-eslint/visitor-keys': 8.46.3 + '@typescript-eslint/project-service': 8.54.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.54.0(typescript@5.9.3) + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/visitor-keys': 8.54.0 debug: 4.4.3 - fast-glob: 3.3.3 - is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.3 - ts-api-utils: 2.1.0(typescript@5.9.3) + tinyglobby: 0.2.15 + ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.46.3(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.54.0(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - '@typescript-eslint/scope-manager': 8.46.3 - '@typescript-eslint/types': 8.46.3 - '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) - eslint: 9.39.1 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@typescript-eslint/scope-manager': 8.54.0 + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) + eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.46.3': + '@typescript-eslint/visitor-keys@8.54.0': dependencies: - '@typescript-eslint/types': 8.46.3 + '@typescript-eslint/types': 8.54.0 eslint-visitor-keys: 4.2.1 '@ungap/structured-clone@1.3.0': {} @@ -7126,23 +7098,23 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@whiskeysockets/baileys@7.0.0-rc.9(link-preview-js@3.1.0)(sharp@0.34.5)': + '@whiskeysockets/baileys@6.7.21(link-preview-js@3.2.0)(sharp@0.34.5)': dependencies: - '@cacheable/node-cache': 1.7.4 + '@cacheable/node-cache': 1.7.6 '@hapi/boom': 9.1.4 async-mutex: 0.5.0 + axios: 1.13.4 libsignal: '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/1c30d7d7e76a3b0aa120b04dc6a26f5a12dccf67' - lru-cache: 11.2.2 - music-metadata: 11.10.0 - p-queue: 9.0.1 + music-metadata: 11.11.0 pino: 9.14.0 protobufjs: 7.5.4 sharp: 0.34.5 - ws: 8.18.3 + ws: 8.19.0 optionalDependencies: - link-preview-js: 3.1.0 + link-preview-js: 3.2.0 transitivePeerDependencies: - bufferutil + - debug - supports-color - utf-8-validate @@ -7219,7 +7191,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 is-string: 1.1.1 @@ -7230,7 +7202,7 @@ snapshots: call-bind: 1.0.8 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 @@ -7239,14 +7211,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 es-shim-unscopables: 1.1.0 array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 es-shim-unscopables: 1.1.0 arraybuffer.prototype.slice@1.0.4: @@ -7254,7 +7226,7 @@ snapshots: array-buffer-byte-length: 1.0.2 call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 es-errors: 1.3.0 get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 @@ -7279,29 +7251,29 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axios@1.12.2: - dependencies: - follow-redirects: 1.15.11 - form-data: 4.0.4 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - axios@1.13.2: dependencies: follow-redirects: 1.15.11 - form-data: 4.0.4 + form-data: 4.0.5 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - babel-jest@30.2.0(@babel/core@7.28.5): + axios@1.13.4: dependencies: - '@babel/core': 7.28.5 + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + babel-jest@30.2.0(@babel/core@7.28.6): + dependencies: + '@babel/core': 7.28.6 '@jest/transform': 30.2.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 7.0.1 - babel-preset-jest: 30.2.0(@babel/core@7.28.5) + babel-preset-jest: 30.2.0(@babel/core@7.28.6) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -7310,7 +7282,7 @@ snapshots: babel-plugin-istanbul@7.0.1: dependencies: - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 6.0.3 @@ -7324,42 +7296,42 @@ snapshots: babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 cosmiconfig: 7.1.0 resolve: 1.22.11 - babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.5): + babel-preset-current-node-syntax@1.2.0(@babel/core@7.28.6): dependencies: - '@babel/core': 7.28.5 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.5) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.5) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.5) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.5) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.5) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.5) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.5) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.5) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.5) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.5) + '@babel/core': 7.28.6 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.28.6) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.6) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.28.6) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.28.6) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.6) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.28.6) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.28.6) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.28.6) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.28.6) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.28.6) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.28.6) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.28.6) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.28.6) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.28.6) - babel-preset-jest@30.2.0(@babel/core@7.28.5): + babel-preset-jest@30.2.0(@babel/core@7.28.6): dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 babel-plugin-jest-hoist: 30.2.0 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.6) balanced-match@1.0.2: {} base64-js@1.5.1: {} - baseline-browser-mapping@2.8.25: {} + baseline-browser-mapping@2.9.18: {} - basic-ftp@5.0.5: {} + basic-ftp@5.1.0: {} bl@4.1.0: dependencies: @@ -7382,13 +7354,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.27.0: + browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.8.25 - caniuse-lite: 1.0.30001754 - electron-to-chromium: 1.5.249 + baseline-browser-mapping: 2.9.18 + caniuse-lite: 1.0.30001766 + electron-to-chromium: 1.5.279 node-releases: 2.0.27 - update-browserslist-db: 1.1.4(browserslist@4.27.0) + update-browserslist-db: 1.2.3(browserslist@4.28.1) bser@2.1.1: dependencies: @@ -7407,21 +7379,20 @@ snapshots: builtin-modules@5.0.0: {} - bundle-require@5.1.0(esbuild@0.25.12): + bundle-require@5.1.0(esbuild@0.27.2): dependencies: - esbuild: 0.25.12 + esbuild: 0.27.2 load-tsconfig: 0.2.5 cac@6.7.14: {} - cacheable@2.1.1: + cacheable@2.3.2: dependencies: - '@cacheable/memoize': 2.0.3 - '@cacheable/memory': 2.0.4 - '@cacheable/utils': 2.2.0 - hookified: 1.12.2 - keyv: 5.5.3 - qified: 0.5.1 + '@cacheable/memory': 2.0.7 + '@cacheable/utils': 2.3.3 + hookified: 1.15.0 + keyv: 5.6.0 + qified: 0.6.0 call-bind-apply-helpers@1.0.2: dependencies: @@ -7446,7 +7417,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001754: {} + caniuse-lite@1.0.30001766: {} chalk@4.1.2: dependencies: @@ -7485,7 +7456,7 @@ snapshots: ci-info@4.3.1: {} - cjs-module-lexer@2.1.1: {} + cjs-module-lexer@2.2.0: {} classnames@2.5.1: {} @@ -7568,11 +7539,11 @@ snapshots: cookie@0.7.2: {} - cookie@1.0.2: {} + cookie@1.1.1: {} - core-js-compat@3.46.0: + core-js-compat@3.48.0: dependencies: - browserslist: 4.27.0 + browserslist: 4.28.1 core-util-is@1.0.3: {} @@ -7587,7 +7558,7 @@ snapshots: cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.1 - js-yaml: 4.1.0 + js-yaml: 4.1.1 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: @@ -7611,7 +7582,7 @@ snapshots: css-what@6.2.2: {} - csstype@3.1.3: {} + csstype@3.2.3: {} curve25519-js@0.0.4: {} @@ -7649,7 +7620,7 @@ snapshots: dependencies: ms: 2.1.3 - dedent@1.7.0(babel-plugin-macros@3.1.0): + dedent@1.7.1(babel-plugin-macros@3.1.0): optionalDependencies: babel-plugin-macros: 3.1.0 @@ -7687,7 +7658,7 @@ snapshots: detect-newline@3.1.0: {} - diff@4.0.2: {} + diff@4.0.4: {} doctrine@2.1.0: dependencies: @@ -7695,8 +7666,8 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.28.4 - csstype: 3.1.3 + '@babel/runtime': 7.28.6 + csstype: 3.2.3 dom-serializer@2.0.0: dependencies: @@ -7762,7 +7733,7 @@ snapshots: dependencies: safe-buffer: 5.2.1 - electron-to-chromium@1.5.249: {} + electron-to-chromium@1.5.279: {} emittery@0.13.1: {} @@ -7782,7 +7753,7 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract@1.24.0: + es-abstract@1.24.1: dependencies: array-buffer-byte-length: 1.0.2 arraybuffer.prototype.slice: 1.0.4 @@ -7837,7 +7808,7 @@ snapshots: typed-array-byte-offset: 1.0.4 typed-array-length: 1.0.7 unbox-primitive: 1.1.0 - which-typed-array: 1.1.19 + which-typed-array: 1.1.20 es-define-property@1.0.1: {} @@ -7864,34 +7835,34 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild@0.25.12: + esbuild@0.27.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 escalade@3.2.0: {} @@ -7909,19 +7880,19 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@10.1.8(eslint@9.39.1): + eslint-config-prettier@10.1.8(eslint@9.39.2): dependencies: - eslint: 9.39.1 + eslint: 9.39.2 - eslint-config-xo-space@0.35.0(eslint@9.39.1): + eslint-config-xo-space@0.35.0(eslint@9.39.2): dependencies: - eslint: 9.39.1 - eslint-config-xo: 0.44.0(eslint@9.39.1) + eslint: 9.39.2 + eslint-config-xo: 0.44.0(eslint@9.39.2) - eslint-config-xo@0.44.0(eslint@9.39.1): + eslint-config-xo@0.44.0(eslint@9.39.2): dependencies: confusing-browser-globals: 1.0.11 - eslint: 9.39.1 + eslint: 9.39.2 eslint-import-resolver-node@0.3.9: dependencies: @@ -7931,23 +7902,23 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.46.3(eslint@9.39.1)(typescript@5.9.3) - eslint: 9.39.1 + '@typescript-eslint/parser': 8.54.0(eslint@9.39.2)(typescript@5.9.3) + eslint: 9.39.2 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-eslint-comments@3.2.0(eslint@9.39.1): + eslint-plugin-eslint-comments@3.2.0(eslint@9.39.2): dependencies: escape-string-regexp: 1.0.5 - eslint: 9.39.1 + eslint: 9.39.2 ignore: 5.3.2 - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -7956,9 +7927,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.1 + eslint: 9.39.2 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.1) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -7970,39 +7941,39 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.54.0(eslint@9.39.2)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@29.0.1(@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(jest@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)))(typescript@5.9.3): + eslint-plugin-jest@29.12.1(@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(jest@30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) - eslint: 9.39.1 + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2)(typescript@5.9.3) + eslint: 9.39.2 optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) - jest: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) + '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + jest: 30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-promise@7.2.1(eslint@9.39.1): + eslint-plugin-promise@7.2.1(eslint@9.39.2): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - eslint: 9.39.1 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + eslint: 9.39.2 - eslint-plugin-unicorn@61.0.2(eslint@9.39.1): + eslint-plugin-unicorn@61.0.2(eslint@9.39.2): dependencies: '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) '@eslint/plugin-kit': 0.3.5 change-case: 5.4.4 ci-info: 4.3.1 clean-regexp: 1.0.0 - core-js-compat: 3.46.0 - eslint: 9.39.1 - esquery: 1.6.0 + core-js-compat: 3.48.0 + eslint: 9.39.2 + esquery: 1.7.0 find-up-simple: 1.0.1 globals: 16.5.0 indent-string: 5.0.0 @@ -8030,15 +8001,15 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.1: + eslint@9.39.2: dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.39.1 + '@eslint/eslintrc': 3.3.3 + '@eslint/js': 9.39.2 '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 @@ -8052,7 +8023,7 @@ snapshots: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 - esquery: 1.6.0 + esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -8077,7 +8048,7 @@ snapshots: esprima@4.0.1: {} - esquery@1.6.0: + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -8091,8 +8062,6 @@ snapshots: esutils@2.0.3: {} - eventemitter3@5.0.1: {} - execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -8116,28 +8085,16 @@ snapshots: jest-mock: 30.2.0 jest-util: 30.2.0 - fast-copy@3.0.2: {} + fast-copy@4.0.2: {} fast-deep-equal@3.1.3: {} - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} fast-safe-stringify@2.1.1: {} - fastq@1.19.1: - dependencies: - reusify: 1.1.0 - fb-watchman@2.0.2: dependencies: bser: 2.1.1 @@ -8146,8 +8103,6 @@ snapshots: optionalDependencies: picomatch: 4.0.3 - fflate@0.8.2: {} - figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 @@ -8156,11 +8111,11 @@ snapshots: dependencies: flat-cache: 4.0.1 - file-type@21.0.0: + file-type@21.3.0: dependencies: - '@tokenizer/inflate': 0.2.7 + '@tokenizer/inflate': 0.4.1 strtok3: 10.3.4 - token-types: 6.1.1 + token-types: 6.1.2 uint8array-extras: 1.5.0 transitivePeerDependencies: - supports-color @@ -8187,7 +8142,7 @@ snapshots: dependencies: magic-string: 0.30.21 mlly: 1.8.0 - rollup: 4.53.1 + rollup: 4.57.0 flat-cache@4.0.1: dependencies: @@ -8212,7 +8167,7 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.4: + form-data@4.0.5: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -8220,7 +8175,7 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 - fs-extra@11.3.2: + fs-extra@11.3.3: dependencies: graceful-fs: 4.2.11 jsonfile: 6.2.0 @@ -8284,21 +8239,17 @@ snapshots: get-uri@6.0.5: dependencies: - basic-ftp: 5.0.5 + basic-ftp: 5.1.0 data-uri-to-buffer: 6.0.2 debug: 4.4.3 transitivePeerDependencies: - supports-color - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - glob@10.4.5: + glob@10.5.0: dependencies: foreground-child: 3.3.1 jackspeak: 3.4.3 @@ -8307,7 +8258,7 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@11.0.3: + glob@11.1.0: dependencies: foreground-child: 3.3.1 jackspeak: 4.1.1 @@ -8316,6 +8267,12 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.1 + glob@13.0.0: + dependencies: + minimatch: 10.1.1 + minipass: 7.1.2 + path-scurry: 2.0.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -8338,12 +8295,10 @@ snapshots: graceful-fs@4.2.11: {} - graphemer@1.4.0: {} - graphile-config@0.0.1-beta.18: dependencies: - '@types/interpret': 1.1.3 - '@types/node': 22.19.0 + '@types/interpret': 1.1.4 + '@types/node': 22.19.7 '@types/semver': 7.7.1 chalk: 4.1.2 debug: 4.4.3 @@ -8358,11 +8313,11 @@ snapshots: dependencies: '@graphile/logger': 0.2.0 '@types/debug': 4.1.12 - '@types/pg': 8.15.6 + '@types/pg': 8.16.0 cosmiconfig: 8.3.6(typescript@5.9.3) graphile-config: 0.0.1-beta.18 json5: 2.2.3 - pg: 8.16.3 + pg: 8.17.2 tslib: 2.8.1 yargs: 17.7.2 transitivePeerDependencies: @@ -8370,7 +8325,7 @@ snapshots: - supports-color - typescript - graphql-request@7.3.1(graphql@16.12.0): + graphql-request@7.4.0(graphql@16.12.0): dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.12.0) graphql: 16.12.0 @@ -8402,6 +8357,10 @@ snapshots: dependencies: has-symbols: 1.1.0 + hashery@1.4.0: + dependencies: + hookified: 1.15.0 + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -8412,7 +8371,7 @@ snapshots: dependencies: react-is: 16.13.1 - hookified@1.12.2: {} + hookified@1.15.0: {} html-escaper@2.0.2: {} @@ -8454,7 +8413,7 @@ snapshots: human-signals@2.1.0: {} - iconv-lite@0.7.0: + iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 @@ -8485,15 +8444,15 @@ snapshots: inherits@2.0.4: {} - inquirer@8.2.7(@types/node@24.10.0): + inquirer@8.2.7(@types/node@24.10.9): dependencies: - '@inquirer/external-editor': 1.0.3(@types/node@24.10.0) + '@inquirer/external-editor': 1.0.3(@types/node@24.10.9) ansi-escapes: 4.3.2 chalk: 4.1.2 cli-cursor: 3.1.0 cli-width: 3.0.0 figures: 3.2.0 - lodash: 4.17.21 + lodash: 4.17.23 mute-stream: 0.0.8 ora: 5.4.1 run-async: 2.4.1 @@ -8513,9 +8472,9 @@ snapshots: interpret@3.1.1: {} - ioredis@5.8.2: + ioredis@5.9.2: dependencies: - '@ioredis/commands': 1.4.0 + '@ioredis/commands': 1.5.0 cluster-key-slot: 1.1.2 debug: 4.4.3 denque: 2.1.0 @@ -8638,7 +8597,7 @@ snapshots: is-typed-array@1.1.15: dependencies: - which-typed-array: 1.1.19 + which-typed-array: 1.1.20 is-unicode-supported@0.1.0: {} @@ -8665,8 +8624,8 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.28.5 - '@babel/parser': 7.28.5 + '@babel/core': 7.28.6 + '@babel/parser': 7.28.6 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.7.3 @@ -8716,10 +8675,10 @@ snapshots: '@jest/expect': 30.2.0 '@jest/test-result': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 chalk: 4.1.2 co: 4.6.0 - dedent: 1.7.0(babel-plugin-macros@3.1.0) + dedent: 1.7.1(babel-plugin-macros@3.1.0) is-generator-fn: 2.1.0 jest-each: 30.2.0 jest-matcher-utils: 30.2.0 @@ -8736,15 +8695,15 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)): + jest-cli@30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)): dependencies: - '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) + '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)) '@jest/test-result': 30.2.0 '@jest/types': 30.2.0 chalk: 4.1.2 exit-x: 0.2.2 import-local: 3.2.0 - jest-config: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) + jest-config: 30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)) jest-util: 30.2.0 jest-validate: 30.2.0 yargs: 17.7.2 @@ -8755,18 +8714,18 @@ snapshots: - supports-color - ts-node - jest-config@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)): + jest-config@30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)): dependencies: - '@babel/core': 7.28.5 + '@babel/core': 7.28.6 '@jest/get-type': 30.1.0 '@jest/pattern': 30.0.1 '@jest/test-sequencer': 30.2.0 '@jest/types': 30.2.0 - babel-jest: 30.2.0(@babel/core@7.28.5) + babel-jest: 30.2.0(@babel/core@7.28.6) chalk: 4.1.2 ci-info: 4.3.1 deepmerge: 4.3.1 - glob: 10.4.5 + glob: 10.5.0 graceful-fs: 4.2.11 jest-circus: 30.2.0(babel-plugin-macros@3.1.0) jest-docblock: 30.2.0 @@ -8782,8 +8741,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 24.10.0 - ts-node: 10.9.2(@types/node@24.10.0)(typescript@5.9.3) + '@types/node': 24.10.9 + ts-node: 10.9.2(@types/node@24.10.9)(typescript@5.9.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -8812,7 +8771,7 @@ snapshots: '@jest/environment': 30.2.0 '@jest/fake-timers': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 jest-mock: 30.2.0 jest-util: 30.2.0 jest-validate: 30.2.0 @@ -8820,7 +8779,7 @@ snapshots: jest-haste-map@30.2.0: dependencies: '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -8853,7 +8812,7 @@ snapshots: jest-message-util@30.2.0: dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.28.6 '@jest/types': 30.2.0 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -8866,7 +8825,7 @@ snapshots: jest-mock@30.2.0: dependencies: '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 jest-util: 30.2.0 jest-pnp-resolver@1.2.3(jest-resolve@30.2.0): @@ -8900,7 +8859,7 @@ snapshots: '@jest/test-result': 30.2.0 '@jest/transform': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 chalk: 4.1.2 emittery: 0.13.1 exit-x: 0.2.2 @@ -8929,11 +8888,11 @@ snapshots: '@jest/test-result': 30.2.0 '@jest/transform': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 chalk: 4.1.2 - cjs-module-lexer: 2.1.1 + cjs-module-lexer: 2.2.0 collect-v8-coverage: 1.0.3 - glob: 10.4.5 + glob: 10.5.0 graceful-fs: 4.2.11 jest-haste-map: 30.2.0 jest-message-util: 30.2.0 @@ -8949,17 +8908,17 @@ snapshots: jest-snapshot@30.2.0: dependencies: - '@babel/core': 7.28.5 - '@babel/generator': 7.28.5 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) - '@babel/types': 7.28.5 + '@babel/core': 7.28.6 + '@babel/generator': 7.28.6 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.28.6) + '@babel/types': 7.28.6 '@jest/expect-utils': 30.2.0 '@jest/get-type': 30.1.0 '@jest/snapshot-utils': 30.2.0 '@jest/transform': 30.2.0 '@jest/types': 30.2.0 - babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5) + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.6) chalk: 4.1.2 expect: 30.2.0 graceful-fs: 4.2.11 @@ -8969,14 +8928,14 @@ snapshots: jest-util: 30.2.0 pretty-format: 30.2.0 semver: 7.7.3 - synckit: 0.11.11 + synckit: 0.11.12 transitivePeerDependencies: - supports-color jest-util@30.2.0: dependencies: '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 chalk: 4.1.2 ci-info: 4.3.1 graceful-fs: 4.2.11 @@ -8995,7 +8954,7 @@ snapshots: dependencies: '@jest/test-result': 30.2.0 '@jest/types': 30.2.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -9004,18 +8963,18 @@ snapshots: jest-worker@30.2.0: dependencies: - '@types/node': 24.10.0 + '@types/node': 24.10.9 '@ungap/structured-clone': 1.3.0 jest-util: 30.2.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)): + jest@30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)): dependencies: - '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) + '@jest/core': 30.2.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)) '@jest/types': 30.2.0 import-local: 3.2.0 - jest-cli: 30.2.0(@types/node@24.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3)) + jest-cli: 30.2.0(@types/node@24.10.9)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -9025,18 +8984,18 @@ snapshots: jose@4.15.9: {} - jose@6.1.1: {} + jose@6.1.3: {} joycon@3.1.1: {} js-tokens@4.0.0: {} - js-yaml@3.14.1: + js-yaml@3.14.2: dependencies: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.1.0: + js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -9064,9 +9023,9 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - jsonwebtoken@9.0.2: + jsonwebtoken@9.0.3: dependencies: - jws: 3.2.2 + jws: 4.0.1 lodash.includes: 4.3.0 lodash.isboolean: 3.0.3 lodash.isinteger: 4.0.4 @@ -9077,22 +9036,22 @@ snapshots: ms: 2.1.3 semver: 7.7.3 - jwa@1.4.2: + jwa@2.0.1: dependencies: buffer-equal-constant-time: 1.0.1 ecdsa-sig-formatter: 1.0.11 safe-buffer: 5.2.1 - jws@3.2.2: + jws@4.0.1: dependencies: - jwa: 1.4.2 + jwa: 2.0.1 safe-buffer: 5.2.1 keyv@4.5.4: dependencies: json-buffer: 3.0.1 - keyv@5.5.3: + keyv@5.6.0: dependencies: '@keyv/serialize': 1.1.1 @@ -9109,12 +9068,12 @@ snapshots: lines-and-columns@1.2.4: {} - link-preview-js@3.1.0: + link-preview-js@3.2.0: dependencies: cheerio: 1.0.0-rc.11 url: 0.11.0 - load-esm@1.0.2: {} + load-esm@1.0.3: {} load-tsconfig@0.2.5: {} @@ -9146,9 +9105,7 @@ snapshots: lodash.once@4.1.1: {} - lodash.sortby@4.7.0: {} - - lodash@4.17.21: {} + lodash@4.17.23: {} log-symbols@4.1.0: dependencies: @@ -9165,7 +9122,7 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.2.2: {} + lru-cache@11.2.5: {} lru-cache@5.1.1: dependencies: @@ -9197,8 +9154,6 @@ snapshots: merge-stream@2.0.0: {} - merge2@1.4.1: {} - micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -9237,7 +9192,7 @@ snapshots: acorn: 8.15.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.6.1 + ufo: 1.6.3 ms@2.1.3: {} @@ -9257,17 +9212,18 @@ snapshots: duplexer2: 0.1.4 object-assign: 4.1.1 - music-metadata@11.10.0: + music-metadata@11.11.0: dependencies: - '@borewit/text-codec': 0.2.0 + '@borewit/text-codec': 0.2.1 '@tokenizer/token': 0.3.0 content-type: 1.0.5 debug: 4.4.3 - file-type: 21.0.0 + file-type: 21.3.0 media-typer: 1.1.0 strtok3: 10.3.4 - token-types: 6.1.1 + token-types: 6.1.2 uint8array-extras: 1.5.0 + win-guid: 0.2.0 transitivePeerDependencies: - supports-color @@ -9289,15 +9245,15 @@ snapshots: next-auth@4.24.13(next@15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 '@panva/hkdf': 1.2.1 cookie: 0.7.2 jose: 4.15.9 next: 15.5.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) oauth: 0.9.15 openid-client: 5.7.1 - preact: 10.27.2 - preact-render-to-string: 5.2.6(preact@10.27.2) + preact: 10.28.2 + preact-render-to-string: 5.2.6(preact@10.28.2) react: 19.2.0 react-dom: 19.2.0(react@19.2.0) uuid: 8.3.2 @@ -9306,7 +9262,7 @@ snapshots: dependencies: '@next/env': 15.5.9 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001754 + caniuse-lite: 1.0.30001766 postcss: 8.4.31 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) @@ -9349,7 +9305,7 @@ snapshots: dependencies: boolbase: 1.0.0 - oauth4webapi@3.8.2: {} + oauth4webapi@3.8.3: {} oauth@0.9.15: {} @@ -9383,14 +9339,14 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 es-object-atoms: 1.1.1 object.groupby@1.0.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 object.values@1.2.1: dependencies: @@ -9461,13 +9417,6 @@ snapshots: dependencies: p-limit: 3.1.0 - p-queue@9.0.1: - dependencies: - eventemitter3: 5.0.1 - p-timeout: 7.0.1 - - p-timeout@7.0.1: {} - p-try@2.2.0: {} pac-proxy-agent@7.2.0: @@ -9496,7 +9445,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.28.6 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -9525,45 +9474,45 @@ snapshots: path-scurry@2.0.1: dependencies: - lru-cache: 11.2.2 + lru-cache: 11.2.5 minipass: 7.1.2 - path-to-regexp@8.2.0: {} + path-to-regexp@8.3.0: {} path-type@4.0.0: {} pathe@2.0.3: {} - pg-cloudflare@1.2.7: + pg-cloudflare@1.3.0: optional: true - pg-connection-string@2.9.1: {} + pg-connection-string@2.10.1: {} pg-int8@1.0.1: {} - pg-pool@3.10.1(pg@8.16.3): + pg-pool@3.11.0(pg@8.17.2): dependencies: - pg: 8.16.3 + pg: 8.17.2 - pg-protocol@1.10.3: {} + pg-protocol@1.11.0: {} pg-types@2.2.0: dependencies: pg-int8: 1.0.1 postgres-array: 2.0.0 - postgres-bytea: 1.0.0 + postgres-bytea: 1.0.1 postgres-date: 1.0.7 postgres-interval: 1.2.0 - pg@8.16.3: + pg@8.17.2: dependencies: - pg-connection-string: 2.9.1 - pg-pool: 3.10.1(pg@8.16.3) - pg-protocol: 1.10.3 + pg-connection-string: 2.10.1 + pg-pool: 3.11.0(pg@8.17.2) + pg-protocol: 1.11.0 pg-types: 2.2.0 pgpass: 1.0.5 optionalDependencies: - pg-cloudflare: 1.2.7 + pg-cloudflare: 1.3.0 pgpass@1.0.5: dependencies: @@ -9579,37 +9528,41 @@ snapshots: dependencies: split2: 4.2.0 - pino-pretty@13.1.2: + pino-abstract-transport@3.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.1.3: dependencies: colorette: 2.0.20 dateformat: 4.6.3 - fast-copy: 3.0.2 + fast-copy: 4.0.2 fast-safe-stringify: 2.1.1 help-me: 5.0.0 joycon: 3.1.1 minimist: 1.2.8 on-exit-leak-free: 2.1.2 - pino-abstract-transport: 2.0.0 + pino-abstract-transport: 3.0.0 pump: 3.0.3 secure-json-parse: 4.1.0 sonic-boom: 4.2.0 strip-json-comments: 5.0.3 - pino-std-serializers@7.0.0: {} + pino-std-serializers@7.1.0: {} - pino@10.1.0: + pino@10.3.0: dependencies: '@pinojs/redact': 0.4.0 atomic-sleep: 1.0.0 on-exit-leak-free: 2.1.2 - pino-abstract-transport: 2.0.0 - pino-std-serializers: 7.0.0 + pino-abstract-transport: 3.0.0 + pino-std-serializers: 7.1.0 process-warning: 5.0.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 safe-stable-stringify: 2.5.0 sonic-boom: 4.2.0 - thread-stream: 3.1.0 + thread-stream: 4.0.0 pino@9.14.0: dependencies: @@ -9617,7 +9570,7 @@ snapshots: atomic-sleep: 1.0.0 on-exit-leak-free: 2.1.2 pino-abstract-transport: 2.0.0 - pino-std-serializers: 7.0.0 + pino-std-serializers: 7.1.0 process-warning: 5.0.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 @@ -9641,12 +9594,12 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-load-config@6.0.1(postcss@8.4.31)(tsx@4.20.6): + postcss-load-config@6.0.1(postcss@8.4.31)(tsx@4.21.0): dependencies: lilconfig: 3.1.3 optionalDependencies: postcss: 8.4.31 - tsx: 4.20.6 + tsx: 4.21.0 postcss@8.4.31: dependencies: @@ -9656,7 +9609,7 @@ snapshots: postgres-array@2.0.0: {} - postgres-bytea@1.0.0: {} + postgres-bytea@1.0.1: {} postgres-date@1.0.7: {} @@ -9664,9 +9617,9 @@ snapshots: dependencies: xtend: 4.0.2 - preact-render-to-string@5.2.6(preact@10.27.2): + preact-render-to-string@5.2.6(preact@10.28.2): dependencies: - preact: 10.27.2 + preact: 10.28.2 pretty-format: 3.8.0 preact-render-to-string@6.5.11(preact@10.24.3): @@ -9675,7 +9628,7 @@ snapshots: preact@10.24.3: {} - preact@10.27.2: {} + preact@10.28.2: {} prelude-ls@1.2.1: {} @@ -9725,7 +9678,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 24.10.0 + '@types/node': 24.10.9 long: 5.3.2 proxy-agent@6.5.0: @@ -9754,20 +9707,18 @@ snapshots: pure-rand@7.0.1: {} - qified@0.5.1: + qified@0.6.0: dependencies: - hookified: 1.12.2 + hookified: 1.15.0 qr.js@0.0.0: {} - qs@6.14.0: + qs@6.14.1: dependencies: side-channel: 1.1.0 querystring@0.2.0: {} - queue-microtask@1.2.3: {} - quick-format-unescaped@4.0.4: {} react-cookie@8.0.1(@types/react@19.2.2)(react@19.2.0): @@ -9793,7 +9744,7 @@ snapshots: react-is@18.3.1: {} - react-is@19.2.0: {} + react-is@19.2.4: {} react-polyglot@0.7.2(node-polyglot@2.6.0)(react@19.2.0): dependencies: @@ -9810,7 +9761,7 @@ snapshots: react-transition-group@4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -9858,7 +9809,7 @@ snapshots: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 es-errors: 1.3.0 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 @@ -9880,9 +9831,7 @@ snapshots: dependencies: jsesc: 3.0.2 - remeda@2.32.0: - dependencies: - type-fest: 4.41.0 + remeda@2.33.4: {} require-directory@2.1.1: {} @@ -9909,42 +9858,39 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 - reusify@1.1.0: {} - - rollup@4.53.1: + rollup@4.57.0: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.1 - '@rollup/rollup-android-arm64': 4.53.1 - '@rollup/rollup-darwin-arm64': 4.53.1 - '@rollup/rollup-darwin-x64': 4.53.1 - '@rollup/rollup-freebsd-arm64': 4.53.1 - '@rollup/rollup-freebsd-x64': 4.53.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.1 - '@rollup/rollup-linux-arm-musleabihf': 4.53.1 - '@rollup/rollup-linux-arm64-gnu': 4.53.1 - '@rollup/rollup-linux-arm64-musl': 4.53.1 - '@rollup/rollup-linux-loong64-gnu': 4.53.1 - '@rollup/rollup-linux-ppc64-gnu': 4.53.1 - '@rollup/rollup-linux-riscv64-gnu': 4.53.1 - '@rollup/rollup-linux-riscv64-musl': 4.53.1 - '@rollup/rollup-linux-s390x-gnu': 4.53.1 - '@rollup/rollup-linux-x64-gnu': 4.53.1 - '@rollup/rollup-linux-x64-musl': 4.53.1 - '@rollup/rollup-openharmony-arm64': 4.53.1 - '@rollup/rollup-win32-arm64-msvc': 4.53.1 - '@rollup/rollup-win32-ia32-msvc': 4.53.1 - '@rollup/rollup-win32-x64-gnu': 4.53.1 - '@rollup/rollup-win32-x64-msvc': 4.53.1 + '@rollup/rollup-android-arm-eabi': 4.57.0 + '@rollup/rollup-android-arm64': 4.57.0 + '@rollup/rollup-darwin-arm64': 4.57.0 + '@rollup/rollup-darwin-x64': 4.57.0 + '@rollup/rollup-freebsd-arm64': 4.57.0 + '@rollup/rollup-freebsd-x64': 4.57.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.57.0 + '@rollup/rollup-linux-arm-musleabihf': 4.57.0 + '@rollup/rollup-linux-arm64-gnu': 4.57.0 + '@rollup/rollup-linux-arm64-musl': 4.57.0 + '@rollup/rollup-linux-loong64-gnu': 4.57.0 + '@rollup/rollup-linux-loong64-musl': 4.57.0 + '@rollup/rollup-linux-ppc64-gnu': 4.57.0 + '@rollup/rollup-linux-ppc64-musl': 4.57.0 + '@rollup/rollup-linux-riscv64-gnu': 4.57.0 + '@rollup/rollup-linux-riscv64-musl': 4.57.0 + '@rollup/rollup-linux-s390x-gnu': 4.57.0 + '@rollup/rollup-linux-x64-gnu': 4.57.0 + '@rollup/rollup-linux-x64-musl': 4.57.0 + '@rollup/rollup-openbsd-x64': 4.57.0 + '@rollup/rollup-openharmony-arm64': 4.57.0 + '@rollup/rollup-win32-arm64-msvc': 4.57.0 + '@rollup/rollup-win32-ia32-msvc': 4.57.0 + '@rollup/rollup-win32-x64-gnu': 4.57.0 + '@rollup/rollup-win32-x64-msvc': 4.57.0 fsevents: 2.3.3 run-async@2.4.1: {} - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - rxjs@7.8.2: dependencies: tslib: 2.8.1 @@ -10111,9 +10057,7 @@ snapshots: source-map@0.6.1: {} - source-map@0.8.0-beta.0: - dependencies: - whatwg-url: 7.1.0 + source-map@0.7.6: {} split2@4.2.0: {} @@ -10153,7 +10097,7 @@ snapshots: call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.24.0 + es-abstract: 1.24.1 es-object-atoms: 1.1.1 has-property-descriptors: 1.0.2 @@ -10211,14 +10155,14 @@ snapshots: stylis@4.2.0: {} - sucrase@3.35.0: + sucrase@3.35.1: dependencies: '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 - glob: 10.4.5 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 + tinyglobby: 0.2.15 ts-interface-checker: 0.1.13 supports-color@7.2.0: @@ -10231,7 +10175,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - synckit@0.11.11: + synckit@0.11.12: dependencies: '@pkgr/core': 0.2.9 @@ -10253,6 +10197,10 @@ snapshots: dependencies: real-require: 0.2.0 + thread-stream@4.0.0: + dependencies: + real-require: 0.2.0 + through2@0.4.2: dependencies: readable-stream: 1.0.34 @@ -10273,39 +10221,35 @@ snapshots: dependencies: is-number: 7.0.0 - token-types@6.1.1: + token-types@6.1.2: dependencies: - '@borewit/text-codec': 0.1.1 + '@borewit/text-codec': 0.2.1 '@tokenizer/token': 0.3.0 ieee754: 1.2.1 tr46@0.0.3: {} - tr46@1.0.1: - dependencies: - punycode: 2.3.1 - tree-kill@1.2.2: {} - ts-api-utils@2.1.0(typescript@5.9.3): + ts-api-utils@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@types/node@24.10.0)(typescript@5.9.3): + ts-node@10.9.2(@types/node@24.10.9)(typescript@5.9.3): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 + '@tsconfig/node10': 1.0.12 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 24.10.0 + '@types/node': 24.10.9 acorn: 8.15.0 acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 - diff: 4.0.2 + diff: 4.0.4 make-error: 1.3.6 typescript: 5.9.3 v8-compile-cache-lib: 3.0.1 @@ -10320,22 +10264,22 @@ snapshots: tslib@2.8.1: {} - tsup@8.5.0(postcss@8.4.31)(tsx@4.20.6)(typescript@5.9.3): + tsup@8.5.1(postcss@8.4.31)(tsx@4.21.0)(typescript@5.9.3): dependencies: - bundle-require: 5.1.0(esbuild@0.25.12) + bundle-require: 5.1.0(esbuild@0.27.2) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 debug: 4.4.3 - esbuild: 0.25.12 + esbuild: 0.27.2 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.4.31)(tsx@4.20.6) + postcss-load-config: 6.0.1(postcss@8.4.31)(tsx@4.21.0) resolve-from: 5.0.0 - rollup: 4.53.1 - source-map: 0.8.0-beta.0 - sucrase: 3.35.0 + rollup: 4.57.0 + source-map: 0.7.6 + sucrase: 3.35.1 tinyexec: 0.3.2 tinyglobby: 0.2.15 tree-kill: 1.2.2 @@ -10348,47 +10292,47 @@ snapshots: - tsx - yaml - tsx@4.20.6: + tsx@4.21.0: dependencies: - esbuild: 0.25.12 + esbuild: 0.27.2 get-tsconfig: 4.13.0 optionalDependencies: fsevents: 2.3.3 - turbo-darwin-64@2.6.0: + turbo-darwin-64@2.7.6: optional: true - turbo-darwin-arm64@2.6.0: + turbo-darwin-arm64@2.7.6: optional: true - turbo-linux-64@2.6.0: + turbo-linux-64@2.7.6: optional: true - turbo-linux-arm64@2.6.0: + turbo-linux-arm64@2.7.6: optional: true - turbo-windows-64@2.6.0: + turbo-windows-64@2.7.6: optional: true - turbo-windows-arm64@2.6.0: + turbo-windows-arm64@2.7.6: optional: true - turbo@2.6.0: + turbo@2.7.6: optionalDependencies: - turbo-darwin-64: 2.6.0 - turbo-darwin-arm64: 2.6.0 - turbo-linux-64: 2.6.0 - turbo-linux-arm64: 2.6.0 - turbo-windows-64: 2.6.0 - turbo-windows-arm64: 2.6.0 + turbo-darwin-64: 2.7.6 + turbo-darwin-arm64: 2.7.6 + turbo-linux-64: 2.7.6 + turbo-linux-arm64: 2.7.6 + turbo-windows-64: 2.7.6 + turbo-windows-arm64: 2.7.6 - twilio@5.10.4: + twilio@5.12.0: dependencies: - axios: 1.13.2 + axios: 1.13.4 dayjs: 1.11.19 https-proxy-agent: 5.0.1 - jsonwebtoken: 9.0.2 - qs: 6.14.0 + jsonwebtoken: 9.0.3 + qs: 6.14.1 scmp: 2.1.0 xmlbuilder: 13.0.2 transitivePeerDependencies: @@ -10403,8 +10347,6 @@ snapshots: type-fest@0.21.3: {} - type-fest@4.41.0: {} - typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -10440,7 +10382,7 @@ snapshots: typescript@5.9.3: {} - ufo@1.6.1: {} + ufo@1.6.3: {} uid@2.0.2: dependencies: @@ -10461,7 +10403,7 @@ snapshots: universal-cookie@8.0.1: dependencies: - cookie: 1.0.2 + cookie: 1.1.1 universalify@2.0.1: {} @@ -10489,9 +10431,9 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - update-browserslist-db@1.1.4(browserslist@4.27.0): + update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: - browserslist: 4.27.0 + browserslist: 4.28.1 escalade: 3.2.0 picocolors: 1.1.1 @@ -10534,19 +10476,11 @@ snapshots: webidl-conversions@3.0.1: {} - webidl-conversions@4.0.2: {} - whatwg-url@5.0.0: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - whatwg-url@7.1.0: - dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -10569,7 +10503,7 @@ snapshots: isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 - which-typed-array: 1.1.19 + which-typed-array: 1.1.20 which-collection@1.0.2: dependencies: @@ -10578,7 +10512,7 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 - which-typed-array@1.1.19: + which-typed-array@1.1.20: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 @@ -10596,6 +10530,8 @@ snapshots: dependencies: isexe: 2.0.0 + win-guid@0.2.0: {} + word-wrap@1.2.5: {} wrap-ansi@6.2.0: @@ -10623,7 +10559,7 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 - ws@8.18.3: {} + ws@8.19.0: {} xml@1.0.1: {} From 59872f579a44b37cbeac8206e4737f3b60057abd Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Mon, 9 Feb 2026 22:18:35 +0100 Subject: [PATCH 23/38] Signal notification fixes and UI updates --- .../controllers/_profile/notification.coffee | 220 ++++++++++++++++++ .../_profile/signal_notifications.coffee | 89 ------- .../_ui_element/notification_matrix.coffee | 15 ++ .../mixins/ticket_notification_matrix.coffee | 29 +++ .../views/generic/notification_matrix.jst.eco | 70 ++++++ .../app/views/profile/notification.jst.eco | 86 +++++++ .../profile/signal_notifications.jst.eco | 86 ------- .../src/app/jobs/signal_notification_job.rb | 14 +- .../models/transaction/signal_notification.rb | 13 +- ...000001_add_signal_notification_settings.rb | 15 +- .../src/lib/signal_notification_sender.rb | 4 +- 11 files changed, 440 insertions(+), 201 deletions(-) create mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/notification.coffee delete mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/signal_notifications.coffee create mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee create mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee create mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/generic/notification_matrix.jst.eco create mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/notification.jst.eco delete mode 100644 packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/signal_notifications.jst.eco diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/notification.coffee b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/notification.coffee new file mode 100644 index 0000000..8a2c7f6 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/notification.coffee @@ -0,0 +1,220 @@ +class ProfileNotification extends App.ControllerSubContent + @include App.TicketNotificationMatrix + + @requiredPermission: 'user_preferences.notifications+ticket.agent' + header: __('Notifications') + events: + 'submit form': 'update' + 'click .js-reset' : 'reset' + 'change .js-notificationSound': 'previewSound' + 'change #profile-groups-limit': 'didSwitchGroupsLimit' + 'change input[name=group_ids]': 'didChangeGroupIds' + 'change input[name$=".channel.signal"]': 'didChangeSignalCheckbox' + + elements: + '#profile-groups-limit': 'profileGroupsLimitInput' + '.profile-groups-limit-settings-inner': 'groupsLimitSettings' + '.profile-groups-all-unchecked': 'groupsAllUncheckedWarning' + + sounds: [ + { + name: 'Bell' + file: 'Bell.mp3' + }, + { + name: 'Kalimba' + file: 'Kalimba.mp3' + }, + { + name: 'Marimba' + file: 'Marimba.mp3' + }, + { + name: 'Peep' + file: 'Peep.mp3' + }, + { + name: 'Plop' + file: 'Plop.mp3' + }, + { + name: 'Ring' + file: 'Ring.mp3' + }, + { + name: 'Space' + file: 'Space.mp3' + }, + { + name: 'Wood' + file: 'Wood.mp3' + }, + { + name: 'Xylo' + file: 'Xylo.mp3' + } + ] + + constructor: -> + super + App.User.full(App.Session.get().id, @render, true, true) + + render: => + + matrix = + create: + name: __('New Ticket') + update: + name: __('Ticket update') + reminder_reached: + name: __('Ticket reminder reached') + escalation: + name: __('Ticket escalation') + + config = + group_ids: [] + matrix: {} + + user_config = @Session.get('preferences').notification_config + if user_config + config = $.extend(true, {}, config, user_config) + + # groups + user_group_config = true + if !user_config || !user_config['group_ids'] || _.isEmpty(user_config['group_ids']) || user_config['group_ids'][0] is '-' + user_group_config = false + + groups = [] + group_ids = App.User.find(@Session.get('id')).allGroupIds() + if group_ids + for group_id in group_ids + group = App.Group.find(group_id) + groups.push group + if !user_group_config + if !config['group_ids'] + config['group_ids'] = [] + config['group_ids'].push group_id.toString() + + groups = _.sortBy(groups, (item) -> return item.name) + + for sound in @sounds + sound.selected = sound.file is App.OnlineNotification.soundFile() ? true : false + + signal_notification_enabled = App.Config.get('signal_notification_enabled') + + signal_uid = config.signal_uid || '' + + # Check if any signal checkbox is currently checked in the matrix + signal_has_checked = false + if signal_notification_enabled + for key, val of config.matrix + if val?.channel?.signal + signal_has_checked = true + break + + @html App.view('profile/notification') + matrixTableHTML: @renderNotificationMatrix(config.matrix) + groups: groups + config: config + sounds: @sounds + notificationSoundEnabled: App.OnlineNotification.soundEnabled() + user_group_config: user_group_config + signal_notification_enabled: signal_notification_enabled + signal_uid: signal_uid + signal_has_checked: signal_has_checked + + update: (e) => + + #notification_config + e.preventDefault() + params = {} + params.notification_config = {} + + formParams = @formParam(e.target) + + params.notification_config.matrix = @updatedNotificationMatrixValues(formParams) + + if formParams.signal_uid? + params.notification_config.signal_uid = formParams.signal_uid + + if @profileGroupsLimitInput.is(':checked') + params.notification_config.group_ids = formParams['group_ids'] + if typeof params.notification_config.group_ids isnt 'object' + params.notification_config.group_ids = [params.notification_config.group_ids] + + if _.isEmpty(params.notification_config.group_ids) + delete params.notification_config.group_ids + + @formDisable(e) + + params.notification_sound = formParams.notification_sound + if !params.notification_sound.enabled + params.notification_sound.enabled = false + else + params.notification_sound.enabled = true + + # get data + @ajax( + id: 'preferences' + type: 'PUT' + url: @apiPath + '/users/preferences' + data: JSON.stringify(params) + processData: true + success: @success + error: @error + ) + + reset: (e) => + new App.ControllerConfirm( + message: __('Are you sure? Your notifications settings will be reset to default.') + buttonClass: 'btn--danger' + callback: => + @ajax( + id: 'preferences_notifications_reset' + type: 'POST' + url: "#{@apiPath}/users/preferences_notifications_reset" + processData: true + success: @success + ) + container: @el.closest('.content') + ) + + + success: (data, status, xhr) => + App.User.full( + App.Session.get('id'), + => + App.Event.trigger('ui:rerender') + @notify( + type: 'success' + msg: __('Update successful.') + ) + , + true + ) + + error: (xhr, status, error) => + @render() + data = JSON.parse(xhr.responseText) + @notify( + type: 'error' + msg: data.message + ) + + previewSound: (e) => + params = @formParam(e.target) + return if !params.notification_sound + return if !params.notification_sound.file + App.OnlineNotification.play(params.notification_sound.file) + + didSwitchGroupsLimit: (e) => + @groupsLimitSettings.collapse('toggle') + + didChangeGroupIds: (e) => + @groupsAllUncheckedWarning.toggleClass 'hide', @el.find('input[name=group_ids]:checked').length != 0 + + didChangeSignalCheckbox: (e) => + hasChecked = @el.find('input[name$=".channel.signal"]:checked').length > 0 + @el.find('.js-signal-phone-container').toggle(hasChecked) + +App.Config.set('Notifications', { prio: 2600, name: __('Notifications'), parent: '#profile', target: '#profile/notifications', permission: ['user_preferences.notifications+ticket.agent'], controller: ProfileNotification }, 'NavBarProfile') diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/signal_notifications.coffee b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/signal_notifications.coffee deleted file mode 100644 index 23d0df7..0000000 --- a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_profile/signal_notifications.coffee +++ /dev/null @@ -1,89 +0,0 @@ -class ProfileSignalNotifications extends App.ControllerSubContent - @requiredPermission: 'user_preferences.signal_notifications+ticket.agent' - header: __('Signal Notifications') - events: - 'submit form': 'update' - - constructor: -> - super - App.User.full(App.Session.get().id, @render, true, true) - - render: => - config = - enabled: false - events: - create: true - update: true - escalation: true - reminder_reached: true - - user = App.User.find(App.Session.get().id) - user_config = user.preferences?.signal_notifications - if user_config - config = $.extend(true, {}, config, user_config) - - @html App.view('profile/signal_notifications') - config: config - signal_uid: user.signal_uid || '' - signal_notification_enabled: App.Config.get('signal_notification_enabled') - - update: (e) => - e.preventDefault() - params = @formParam(e.target) - - preferences = {} - preferences.signal_notifications = - enabled: params.enabled == 'true' - events: - create: params.event_create == 'true' - update: params.event_update == 'true' - escalation: params.event_escalation == 'true' - reminder_reached: params.event_reminder_reached == 'true' - - @formDisable(e) - - @ajax( - id: 'preferences_signal_notifications' - type: 'PUT' - url: @apiPath + '/users/preferences' - data: JSON.stringify(preferences) - processData: true - success: @successPreferences - error: @error - ) - - if params.signal_uid? - user = App.User.find(App.Session.get().id) - user.signal_uid = params.signal_uid - user.save( - done: => - # User saved successfully - fail: (settings, details) => - @notify( - type: 'error' - msg: details.error || __('Failed to save Signal phone number') - ) - ) - - successPreferences: (data, status, xhr) => - App.User.full( - App.Session.get('id'), - => - App.Event.trigger('ui:rerender') - @notify( - type: 'success' - msg: __('Update successful.') - ) - , - true - ) - - error: (xhr, status, error) => - @render() - data = JSON.parse(xhr.responseText) - @notify( - type: 'error' - msg: data.message - ) - -App.Config.set('SignalNotifications', { prio: 2650, name: __('Signal Notifications'), parent: '#profile', target: '#profile/signal_notifications', permission: ['user_preferences.signal_notifications+ticket.agent'], controller: ProfileSignalNotifications }, 'NavBarProfile') diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee new file mode 100644 index 0000000..e7550c1 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee @@ -0,0 +1,15 @@ +# coffeelint: disable=camel_case_classes +class App.UiElement.notification_matrix + @render: (values, options = {}) -> + + matrixYAxe = + create: + name: __('New Ticket') + update: + name: __('Ticket update') + reminder_reached: + name: __('Ticket reminder reached') + escalation: + name: __('Ticket escalation') + + $( App.view('generic/notification_matrix')( matrixYAxe: matrixYAxe, values: values, signal_notification_enabled: options.signal_notification_enabled ) ) diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee new file mode 100644 index 0000000..407d897 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee @@ -0,0 +1,29 @@ +# Common handling for the notification matrix +App.TicketNotificationMatrix = + renderNotificationMatrix: (values) -> + App.UiElement.notification_matrix.render(values, signal_notification_enabled: App.Config.get('signal_notification_enabled'))[0].outerHTML + + updatedNotificationMatrixValues: (formParams) -> + matrix = {} + + for key, value of formParams + area = key.split('.') + + continue if area[0] isnt 'matrix' + + if !matrix[area[1]] + matrix[area[1]] = {} + + switch area[2] + when 'criteria' + if !matrix[area[1]][area[2]] + matrix[area[1]][area[2]] = {} + + matrix[area[1]][area[2]][area[3]] = value is 'true' + when 'channel' + if !matrix[area[1]][area[2]] + matrix[area[1]][area[2]] = { online: true } + + matrix[area[1]][area[2]][area[3]] = value is 'true' + + matrix diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/generic/notification_matrix.jst.eco b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/generic/notification_matrix.jst.eco new file mode 100644 index 0000000..49c9e1a --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/generic/notification_matrix.jst.eco @@ -0,0 +1,70 @@ +<% if @signal_notification_enabled: %> + <% colWidth = "13%" %> + <% channelWidth = "100px" %> +<% else: %> + <% colWidth = "16%" %> + <% channelWidth = "120px" %> +<% end %> + + + + + + <% if @matrixYAxe: %> + <% for key, value of @matrixYAxe: %> + + +
+ <%- @T('My Tickets') %> + <%- @T('Not Assigned') %>* + <%- @T('Subscribed Tickets') %> + <%- @T('All Tickets') %>* + <%- @T('Also notify via email') %> + <% if @signal_notification_enabled: %> + <%- @T('Also notify via Signal') %> + <% end %> +
+ <%- @T(value.name) %> + <% criteria = @values[key]?.criteria %> + <% channel = @values[key]?.channel %> + + + + + + + + + + + <% if @signal_notification_enabled: %> + + + <% end %> + <% end %> + <% end %> +
diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/notification.jst.eco b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/notification.jst.eco new file mode 100644 index 0000000..65e43f9 --- /dev/null +++ b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/notification.jst.eco @@ -0,0 +1,86 @@ + + +
+ +
+ <%- @matrixTableHTML %> +
+ + <% if @signal_notification_enabled: %> +
+

<%- @T('Signal Phone Number') %>

+
+ +

<%- @T('Use international format with country code (e.g., +1234567890)') %>

+
+
+ <% end %> + + <% if @groups: %> +
+ checked <% end %>> + +
+

+ <%- @T('Limit Groups') %> +

+ +
+
+ + + + + + + + <% for group in @groups: %> + + +
<%- @T('Group') %> + <%- @T('Not Assigned') %> & <%- @T('All Tickets') %> +
<%- @P(group, 'name') %> + + + <% end %> +
+
+
+ <% end %> + +

<%- @T('Sounds') %>

+
+
+ +
+
+ + <%- @Icon('arrow-down') %> +
+
+
+ +
+ + + +
diff --git a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/signal_notifications.jst.eco b/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/signal_notifications.jst.eco deleted file mode 100644 index 4899934..0000000 --- a/packages/zammad-addon-bridge/src/app/assets/javascripts/app/views/profile/signal_notifications.jst.eco +++ /dev/null @@ -1,86 +0,0 @@ - - -<% if !@signal_notification_enabled: %> - -<% end %> - -
-

<%- @T('Signal Phone Number') %>

-

- <%- @T('Enter your Signal phone number to receive ticket notifications via Signal.') %> -

- -
- - -

<%- @T('Use international format with country code (e.g., +1234567890)') %>

-
- -

<%- @T('Notification Settings') %>

- -
- -
- -

<%- @T('Notification Events') %>

-

- <%- @T('Select which events should trigger Signal notifications.') %> -

- -
- -
- -
- -
- -
- -
- -
- -
- - -
diff --git a/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb b/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb index 7c23a3c..c960196 100644 --- a/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb +++ b/packages/zammad-addon-bridge/src/app/jobs/signal_notification_job.rb @@ -11,7 +11,9 @@ class SignalNotificationJob < ApplicationJob user = User.find_by(id: user_id) return if !user - return if user.signal_uid.blank? + + signal_uid = user.preferences.dig('notification_config', 'signal_uid').presence + return if signal_uid.blank? article = article_id ? Ticket::Article.find_by(id: article_id) : nil @@ -30,13 +32,13 @@ class SignalNotificationJob < ApplicationJob SignalNotificationSender.send_message( channel: channel, - recipient: user.signal_uid, + recipient: signal_uid, message: message ) - add_history(ticket, user, type) + add_history(ticket, user, signal_uid, type) - Rails.logger.info "Sent Signal notification to #{user.signal_uid} for ticket ##{ticket.number} (#{type})" + Rails.logger.info "Sent Signal notification to #{signal_uid} for ticket ##{ticket.number} (#{type})" end private @@ -48,8 +50,8 @@ class SignalNotificationJob < ApplicationJob Channel.find_by(id: channel_id, area: 'Signal::Number', active: true) end - def add_history(ticket, user, type) - identifier = user.signal_uid.presence || user.login + def add_history(ticket, user, signal_uid, type) + identifier = signal_uid.presence || user.login recipient_list = "#{identifier}(#{type}:signal)" History.add( diff --git a/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb b/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb index 415c441..5cb2af0 100644 --- a/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb +++ b/packages/zammad-addon-bridge/src/app/models/transaction/signal_notification.rb @@ -91,9 +91,8 @@ class Transaction::SignalNotification possible_recipients_with_ooo.each do |user| next if recipient_is_current_user?(user) next if !user.active? - next if !user_has_signal_notifications_enabled?(user) - next if user.signal_uid.blank? - next if !should_notify_for_event?(user) + next if user_signal_uid(user).blank? + next if !user_wants_signal_for_event?(user) recipients.push(user) end @@ -123,11 +122,11 @@ class Transaction::SignalNotification false end - def user_has_signal_notifications_enabled?(user) - user.preferences.dig('signal_notifications', 'enabled') == true + def user_signal_uid(user) + user.preferences.dig('notification_config', 'signal_uid').presence end - def should_notify_for_event?(user) + def user_wants_signal_for_event?(user) event_type = @item[:type] return false if event_type.blank? @@ -139,6 +138,6 @@ class Transaction::SignalNotification else return false end - user.preferences.dig('signal_notifications', 'events', event_key) == true + user.preferences.dig('notification_config', 'matrix', event_key, 'channel', 'signal') == true end end diff --git a/packages/zammad-addon-bridge/src/db/addon/bridge/20260120000001_add_signal_notification_settings.rb b/packages/zammad-addon-bridge/src/db/addon/bridge/20260120000001_add_signal_notification_settings.rb index 9e1bf23..e894ae2 100644 --- a/packages/zammad-addon-bridge/src/db/addon/bridge/20260120000001_add_signal_notification_settings.rb +++ b/packages/zammad-addon-bridge/src/db/addon/bridge/20260120000001_add_signal_notification_settings.rb @@ -57,20 +57,13 @@ class AddSignalNotificationSettings < ActiveRecord::Migration[5.2] frontend: false ) - # Permission for Signal notifications profile page - Permission.create_if_not_exists( - name: 'user_preferences.signal_notifications', - description: 'Manage Signal notification preferences', - preferences: { - translations: ['Profile - Signal Notifications'] - } - ) end def self.down + # Only destroy the transaction backend registration. + # Preserve signal_notification_enabled and signal_notification_channel_id + # so admin configuration survives addon reinstalls (setup.rb runs + # uninstall + install on every container start). Setting.find_by(name: '0105_signal_notification')&.destroy - Setting.find_by(name: 'signal_notification_enabled')&.destroy - Setting.find_by(name: 'signal_notification_channel_id')&.destroy - Permission.find_by(name: 'user_preferences.signal_notifications')&.destroy end end diff --git a/packages/zammad-addon-bridge/src/lib/signal_notification_sender.rb b/packages/zammad-addon-bridge/src/lib/signal_notification_sender.rb index 8528892..861a6c8 100644 --- a/packages/zammad-addon-bridge/src/lib/signal_notification_sender.rb +++ b/packages/zammad-addon-bridge/src/lib/signal_notification_sender.rb @@ -23,8 +23,8 @@ class SignalNotificationSender return if recipient.blank? return if message.blank? - api_url = channel.options[:api_url] - api_token = channel.options[:api_token] + api_url = channel.options['bot_endpoint'] || channel.options[:bot_endpoint] + api_token = channel.options['bot_token'] || channel.options[:bot_token] return if api_url.blank? || api_token.blank? From e941353b64e6f19178bd3cca0d40ae59aebf5c59 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Tue, 10 Feb 2026 08:36:04 +0100 Subject: [PATCH 24/38] Repo cleanup --- .gitignore | 3 +- .gitlab-ci.yml | 33 - apps/bridge-frontend/.eslintrc.json | 3 - apps/bridge-frontend/.gitignore | 36 - apps/bridge-frontend/Dockerfile | 54 -- apps/bridge-frontend/README.md | 133 --- .../app/(login)/login/page.tsx | 14 - .../app/(main)/[...segment]/@create/page.tsx | 12 - .../app/(main)/[...segment]/@detail/page.tsx | 28 - .../app/(main)/[...segment]/@edit/page.tsx | 28 - .../app/(main)/[...segment]/layout.tsx | 3 - .../app/(main)/[...segment]/page.tsx | 23 - apps/bridge-frontend/app/(main)/layout.tsx | 9 - apps/bridge-frontend/app/(main)/page.tsx | 5 - .../app/_components/InternalLayout.tsx | 29 - .../bridge-frontend/app/_components/Login.tsx | 185 ---- .../app/_components/Sidebar.tsx | 399 -------- .../app/_images/link-logo-small.png | Bin 4668 -> 0 bytes .../app/_lib/authentication.ts | 13 - .../[service]/bots/[token]/receive/route.ts | 1 - .../[service]/bots/[token]/relink/route.ts | 1 - .../app/api/[service]/bots/[token]/route.ts | 1 - .../api/[service]/bots/[token]/send/route.ts | 1 - .../app/api/[service]/webhooks/route.ts | 3 - .../app/api/auth/[...nextauth]/route.ts | 9 - apps/bridge-frontend/app/layout.tsx | 23 - apps/bridge-frontend/docker-entrypoint.sh | 7 - apps/bridge-frontend/middleware.ts | 82 -- apps/bridge-frontend/next.config.js | 7 - apps/bridge-frontend/package.json | 40 - apps/bridge-frontend/public/robots.txt | 2 - apps/bridge-frontend/tsconfig.json | 41 - apps/bridge-migrations/README.md | 158 ---- apps/bridge-migrations/migrate.ts | 96 -- .../migrations/0001-add-next-auth.ts | 72 -- .../migrations/0002-add-signal.ts | 33 - .../migrations/0003-add-whatsapp.ts | 33 - .../migrations/0004-add-voice.ts | 77 -- .../migrations/0005-add-facebook.ts | 36 - .../migrations/0006-add-webhooks.ts | 41 - .../migrations/0007-add-settings.ts | 28 - .../migrations/0008-add-user-role.ts | 9 - apps/bridge-migrations/package.json | 25 - apps/bridge-whatsapp/package.json | 9 +- .../bridge-whatsapp/src}/attachments.ts | 0 apps/bridge-whatsapp/src/index.ts | 2 +- .../bridge-whatsapp/src/lib/logger.ts | 34 +- apps/bridge-whatsapp/src/service.ts | 17 +- apps/bridge-whatsapp/tsconfig.json | 21 +- apps/bridge-worker/.dockerignore | 12 - apps/bridge-worker/Dockerfile | 45 - apps/bridge-worker/README.md | 144 --- apps/bridge-worker/crontab | 2 - apps/bridge-worker/docker-entrypoint.sh | 5 - apps/bridge-worker/graphile.config.ts | 16 - apps/bridge-worker/index.ts | 46 - apps/bridge-worker/lib/common.ts | 20 - apps/bridge-worker/lib/db.ts | 56 -- apps/bridge-worker/lib/facebook.ts | 0 .../lib/formstack-field-mapping.ts | 272 ------ apps/bridge-worker/lib/media-convert.ts | 87 -- apps/bridge-worker/lib/tag-map.ts | 69 -- apps/bridge-worker/lib/utils.ts | 26 - apps/bridge-worker/lib/voice.ts | 0 apps/bridge-worker/lib/whatsapp.ts | 0 apps/bridge-worker/lib/zammad.ts | 171 ---- apps/bridge-worker/package.json | 30 - .../tasks/check-group-membership.ts | 121 --- .../tasks/common/notify-webhooks.ts | 72 -- .../facebook/receive-facebook-message.ts | 34 - .../tasks/facebook/send-facebook-message.ts | 43 - .../tasks/fetch-signal-messages.ts | 258 ----- .../formstack/create-ticket-from-form.ts | 436 --------- .../tasks/signal/receive-signal-message.ts | 230 ----- .../tasks/signal/send-signal-message.ts | 343 ------- .../tasks/voice/receive-voice-message.ts | 11 - .../tasks/voice/send-voice-message.ts | 11 - .../tasks/voice/twilio-recording.ts | 104 --- .../tasks/voice/voice-line-audio-update.ts | 48 - .../tasks/voice/voice-line-delete.ts | 43 - .../tasks/voice/voice-line-provider-update.ts | 40 - .../whatsapp/receive-whatsapp-message.ts | 50 - .../tasks/whatsapp/send-whatsapp-message.ts | 68 -- apps/bridge-worker/tsconfig.json | 8 - apps/link/.dockerignore | 2 - apps/link/.gitignore | 4 - apps/link/Dockerfile | 59 -- apps/link/LICENSE.md | 616 ------------ apps/link/README.md | 106 --- .../app/(login)/login/_components/Login.tsx | 274 ------ apps/link/app/(login)/login/page.tsx | 19 - .../app/(main)/_components/ClientOnly.tsx | 15 - .../(main)/_components/DefaultDashboard.tsx | 13 - .../app/(main)/_components/InternalLayout.tsx | 35 - .../link/app/(main)/_components/SearchBox.tsx | 145 --- .../(main)/_components/SetupModeWarning.tsx | 27 - apps/link/app/(main)/_components/Sidebar.tsx | 463 --------- .../app/(main)/_components/StyledDataGrid.tsx | 95 -- .../app/(main)/_components/ZammadWrapper.tsx | 154 --- .../bridge/[...segment]/@create/page.tsx | 12 - .../bridge/[...segment]/@detail/page.tsx | 28 - .../admin/bridge/[...segment]/@edit/page.tsx | 28 - .../admin/bridge/[...segment]/layout.tsx | 3 - .../(main)/admin/bridge/[...segment]/page.tsx | 23 - apps/link/app/(main)/admin/bridge/page.tsx | 5 - .../link/app/(main)/admin/opensearch/page.tsx | 10 - .../(main)/docs/_components/DocsWrapper.tsx | 29 - apps/link/app/(main)/docs/page.tsx | 10 - apps/link/app/(main)/layout.tsx | 23 - apps/link/app/(main)/logout/page.tsx | 20 - apps/link/app/(main)/page.tsx | 10 - .../app/(main)/setup/_components/Setup.tsx | 38 - apps/link/app/(main)/setup/page.tsx | 10 - apps/link/app/_actions/groups.ts | 24 - apps/link/app/_actions/search.ts | 20 - apps/link/app/_actions/tickets.ts | 205 ---- apps/link/app/_actions/users.ts | 70 -- apps/link/app/_components/Button.tsx | 34 - apps/link/app/_components/DisplayError.tsx | 22 - apps/link/app/_components/MultiProvider.tsx | 29 - .../app/_components/OpenSearchWrapper.tsx | 44 - .../app/_components/ZammadLoginProvider.tsx | 36 - .../link/app/_graphql/createTicketMutation.ts | 10 - .../app/_graphql/getTicketArticlesQuery.ts | 27 - .../_graphql/getTicketOverviewCountsQuery.ts | 19 - apps/link/app/_graphql/getTicketQuery.ts | 33 - apps/link/app/_graphql/searchQuery.ts | 20 - apps/link/app/_graphql/updateTagsMutation.ts | 12 - .../link/app/_graphql/updateTicketMutation.ts | 13 - apps/link/app/_lib/authentication.ts | 180 ---- apps/link/app/_lib/zammad.ts | 68 -- apps/link/app/_styles/global.css | 94 -- .../[service]/bots/[token]/receive/route.ts | 4 - .../[service]/bots/[token]/relink/route.ts | 4 - .../app/api/[service]/bots/[token]/route.ts | 4 - .../api/[service]/bots/[token]/send/route.ts | 4 - apps/link/app/api/[service]/webhooks/route.ts | 6 - apps/link/app/api/auth/[...nextauth]/route.ts | 9 - apps/link/app/api/formstack/route.ts | 98 -- apps/link/app/api/logout/route.ts | 43 - apps/link/app/api/v2/users/route.ts | 7 - apps/link/app/error.tsx | 11 - apps/link/app/layout.tsx | 27 - apps/link/docker-entrypoint.sh | 7 - apps/link/middleware.ts | 170 ---- apps/link/next-env.d.ts | 6 - apps/link/next.config.js | 41 - apps/link/package.json | 48 - apps/link/public/link-logo-small.png | Bin 4668 -> 0 bytes apps/link/public/robots.txt | 2 - apps/link/public/silence.mp3 | Bin 477 -> 0 bytes apps/link/tsconfig.json | 29 - docker/compose/bridge-whatsapp.yml | 2 +- docker/compose/bridge.yml | 40 - docker/compose/link.yml | 36 - docker/compose/zammad.yml | 3 + docker/scripts/docker.js | 18 +- docker/zammad/setup.rb | 3 +- package.json | 41 +- packages/bridge-common/index.ts | 20 - packages/bridge-common/lib/config/signal.ts | 29 - packages/bridge-common/lib/database.ts | 197 ---- packages/bridge-common/lib/utils.ts | 13 - packages/bridge-common/package.json | 23 - packages/bridge-common/tsconfig.json | 12 - packages/bridge-ui/actions/service.ts | 127 --- packages/bridge-ui/components/Create.tsx | 125 --- .../bridge-ui/components/DeleteDialog.tsx | 33 - packages/bridge-ui/components/Detail.tsx | 191 ---- packages/bridge-ui/components/Edit.tsx | 122 --- packages/bridge-ui/components/Home.tsx | 10 - packages/bridge-ui/components/List.tsx | 40 - packages/bridge-ui/components/QRCode.tsx | 60 -- .../bridge-ui/components/ServiceLayout.tsx | 33 - packages/bridge-ui/config/config.ts | 33 - packages/bridge-ui/config/facebook.ts | 122 --- packages/bridge-ui/config/signal.ts | 106 --- packages/bridge-ui/config/users.ts | 74 -- packages/bridge-ui/config/voice.ts | 77 -- packages/bridge-ui/config/webhooks.ts | 168 ---- packages/bridge-ui/config/whatsapp.ts | 121 --- packages/bridge-ui/images.d.ts | 16 - packages/bridge-ui/index.ts | 14 - packages/bridge-ui/lib/actions.ts | 84 -- packages/bridge-ui/lib/facebook.ts | 33 - packages/bridge-ui/lib/frontendUtils.ts | 10 - packages/bridge-ui/lib/routing.ts | 30 - packages/bridge-ui/lib/service.ts | 129 --- packages/bridge-ui/lib/signal.ts | 46 - packages/bridge-ui/lib/utils.ts | 19 - packages/bridge-ui/lib/voice.ts | 3 - packages/bridge-ui/lib/whatsapp.ts | 60 -- packages/bridge-ui/package.json | 25 - packages/bridge-ui/styles/theme.ts | 110 --- packages/bridge-ui/tsconfig.json | 32 - packages/eslint-config/CHANGELOG.md | 90 -- packages/eslint-config/LICENSE.md | 616 ------------ packages/eslint-config/README.md | 59 -- packages/eslint-config/index.js | 2 - packages/eslint-config/package.json | 33 - .../patch/modern-module-resolution.js | 4 - packages/eslint-config/profile/browser.js | 6 - packages/eslint-config/profile/common.js | 113 --- packages/eslint-config/profile/cypress.js | 9 - packages/eslint-config/profile/jest.js | 14 - packages/eslint-config/profile/node.js | 9 - packages/eslint-config/profile/typescript.js | 23 - packages/jest-config/index.js | 2 - packages/jest-config/jest-preset.js | 21 - packages/jest-config/package.json | 18 - packages/logger/package.json | 36 - packages/logger/src/index.ts | 35 - packages/logger/tsconfig.json | 21 - packages/signal-api/.eslintrc.js | 4 - packages/signal-api/.openapi-generator-ignore | 23 - packages/signal-api/apis/AccountsApi.ts | 326 ------- packages/signal-api/apis/AttachmentsApi.ts | 169 ---- packages/signal-api/apis/ContactsApi.ts | 138 --- packages/signal-api/apis/DevicesApi.ts | 343 ------- packages/signal-api/apis/GeneralApi.ts | 338 ------- packages/signal-api/apis/GroupsApi.ts | 879 ------------------ packages/signal-api/apis/IdentitiesApi.ts | 168 ---- packages/signal-api/apis/MessagesApi.ts | 371 -------- packages/signal-api/apis/ProfilesApi.ts | 96 -- packages/signal-api/apis/ReactionsApi.ts | 143 --- packages/signal-api/apis/ReceiptsApi.ts | 85 -- packages/signal-api/apis/SearchApi.ts | 95 -- packages/signal-api/apis/StickerPacksApi.ts | 161 ---- packages/signal-api/apis/index.ts | 15 - packages/signal-api/index.ts | 5 - .../signal-api/models/ApiAddDeviceRequest.ts | 64 -- .../models/ApiAddStickerPackRequest.ts | 74 -- .../models/ApiChangeGroupAdminsRequest.ts | 66 -- .../models/ApiChangeGroupMembersRequest.ts | 66 -- .../signal-api/models/ApiConfiguration.ts | 72 -- .../models/ApiCreateGroupRequest.ts | 119 --- .../models/ApiCreateGroupResponse.ts | 66 -- packages/signal-api/models/ApiError.ts | 60 -- .../signal-api/models/ApiGroupPermissions.ts | 92 -- .../models/ApiLoggingConfiguration.ts | 66 -- .../models/ApiRateLimitChallengeRequest.ts | 75 -- packages/signal-api/models/ApiReaction.ts | 85 -- packages/signal-api/models/ApiReceipt.ts | 87 -- .../models/ApiRegisterNumberRequest.ts | 74 -- .../signal-api/models/ApiSearchResponse.ts | 70 -- .../signal-api/models/ApiSendMessageError.ts | 73 -- .../models/ApiSendMessageResponse.ts | 66 -- .../signal-api/models/ApiSendMessageV1.ts | 95 -- .../signal-api/models/ApiSendMessageV2.ts | 168 ---- .../models/ApiSetUsernameRequest.ts | 66 -- .../models/ApiTrustIdentityRequest.ts | 80 -- .../signal-api/models/ApiTrustModeRequest.ts | 64 -- .../signal-api/models/ApiTrustModeResponse.ts | 64 -- .../models/ApiTypingIndicatorRequest.ts | 66 -- .../models/ApiUnregisterNumberRequest.ts | 76 -- .../models/ApiUpdateAccountSettingsRequest.ts | 78 -- .../models/ApiUpdateContactRequest.ts | 85 -- .../models/ApiUpdateGroupRequest.ts | 83 -- .../models/ApiUpdateProfileRequest.ts | 75 -- .../models/ApiVerifyNumberSettings.ts | 66 -- packages/signal-api/models/ClientAbout.ts | 93 -- .../signal-api/models/ClientGroupEntry.ts | 128 --- .../signal-api/models/ClientIdentityEntry.ts | 97 -- ...ClientListInstalledStickerPacksResponse.ts | 98 -- .../models/ClientSetUsernameResponse.ts | 75 -- packages/signal-api/models/index.ts | 37 - packages/signal-api/openapitools.json | 7 - packages/signal-api/package.json | 21 - packages/signal-api/runtime.ts | 426 --------- packages/signal-api/tsconfig.json | 9 - packages/typescript-config/CHANGELOG.md | 28 - packages/typescript-config/LICENSE.md | 616 ------------ packages/typescript-config/README.md | 55 -- packages/typescript-config/index.js | 2 - packages/typescript-config/package.json | 20 - packages/typescript-config/tsconfig.json | 15 - packages/typescript-config/tsconfig.next.json | 17 - packages/typescript-config/tsconfig.node.json | 12 - packages/ui/components/Autocomplete.tsx | 42 - packages/ui/components/Button.tsx | 99 -- packages/ui/components/Detail.tsx | 26 - packages/ui/components/Dialog.tsx | 112 --- packages/ui/components/DisplayTextField.tsx | 77 -- packages/ui/components/List.tsx | 111 --- packages/ui/components/MultiValueField.tsx | 126 --- packages/ui/components/Select.tsx | 65 -- packages/ui/components/Sidebar.tsx | 350 ------- packages/ui/components/SidebarItem.tsx | 135 --- packages/ui/components/TextField.tsx | 71 -- packages/ui/index.ts | 15 - packages/ui/package.json | 24 - packages/ui/styles/theme.ts | 118 --- packages/ui/tsconfig.json | 32 - packages/zammad-addon-bridge/package.json | 15 - .../src/lib/cdr_signal_api.rb | 50 - .../src/lib/cdr_whatsapp_api.rb | 43 - packages/zammad-addon-bridge/turbo.json | 9 - packages/zammad-addon-common/package.json | 22 - packages/zammad-addon-common/tsconfig.json | 25 - packages/zammad-addon-hardening/README.md | 55 -- packages/zammad-addon-hardening/package.json | 15 - .../zammad-addon-hardening/src/.ruby-version | 1 - .../views/mailer/ticket_create/cs.html.erb | 9 - .../views/mailer/ticket_create/de.html.erb | 8 - .../views/mailer/ticket_create/en.html.erb | 9 - .../views/mailer/ticket_create/es.html.erb | 9 - .../views/mailer/ticket_create/fr.html.erb | 9 - .../views/mailer/ticket_create/it.html.erb | 8 - .../views/mailer/ticket_create/pl.html.erb | 9 - .../views/mailer/ticket_create/pt-br.html.erb | 9 - .../views/mailer/ticket_create/zh-cn.html.erb | 9 - .../views/mailer/ticket_create/zh-tw.html.erb | 8 - .../mailer/ticket_escalation/cs.html.erb | 8 - .../mailer/ticket_escalation/de.html.erb | 8 - .../mailer/ticket_escalation/en.html.erb | 9 - .../mailer/ticket_escalation/es.html.erb | 9 - .../mailer/ticket_escalation/fr.html.erb | 9 - .../mailer/ticket_escalation/it.html.erb | 18 - .../mailer/ticket_escalation/pl.html.erb | 8 - .../mailer/ticket_escalation/pt-br.html.erb | 9 - .../mailer/ticket_escalation/zh-cn.html.erb | 9 - .../mailer/ticket_escalation/zh-tw.html.erb | 9 - .../ticket_escalation_warning/cs.html.erb | 9 - .../ticket_escalation_warning/de.html.erb | 9 - .../ticket_escalation_warning/en.html.erb | 9 - .../ticket_escalation_warning/es.html.erb | 9 - .../ticket_escalation_warning/fr.html.erb | 9 - .../ticket_escalation_warning/it.html.erb | 9 - .../ticket_escalation_warning/pl.html.erb | 9 - .../ticket_escalation_warning/pt-br.html.erb | 10 - .../ticket_escalation_warning/zh-cn.html.erb | 9 - .../ticket_escalation_warning/zh-tw.html.erb | 9 - .../ticket_reminder_reached/cs.html.erb | 9 - .../ticket_reminder_reached/de.html.erb | 9 - .../ticket_reminder_reached/en.html.erb | 9 - .../ticket_reminder_reached/es.html.erb | 9 - .../ticket_reminder_reached/fr.html.erb | 9 - .../ticket_reminder_reached/it.html.erb | 9 - .../ticket_reminder_reached/pt-br.html.erb | 9 - .../ticket_reminder_reached/zh-cn.html.erb | 9 - .../ticket_reminder_reached/zh-tw.html.erb | 9 - .../views/mailer/ticket_update/cs.html.erb | 11 - .../views/mailer/ticket_update/de.html.erb | 11 - .../views/mailer/ticket_update/en.html.erb | 11 - .../views/mailer/ticket_update/es.html.erb | 11 - .../views/mailer/ticket_update/fr.html.erb | 11 - .../views/mailer/ticket_update/it.html.erb | 11 - .../views/mailer/ticket_update/pt-br.html.erb | 11 - .../views/mailer/ticket_update/zh-cn.html.erb | 11 - .../views/mailer/ticket_update/zh-tw.html.erb | 11 - .../src/db/addon/hardening/.gitkeep | 0 packages/zammad-addon-hardening/turbo.json | 9 - .../README.md | 12 +- packages/zammad-addon-link/package.json | 18 + .../scripts}/build.ts | 18 +- .../scripts}/migrate.ts | 0 .../src/.ruby-version | 0 .../controllers/_channel/cdr_signal.coffee | 0 .../app/controllers/_channel/cdr_voice.coffee | 0 .../controllers/_channel/cdr_whatsapp.coffee | 0 .../controllers/_profile/notification.coffee | 0 .../_ui_element/notification_matrix.coffee | 0 .../cdr_link_channel_filter.coffee | 0 .../article_action/cdr_signal.coffee | 0 .../article_action/cdr_whatsapp.coffee | 0 .../mixins/ticket_notification_matrix.coffee | 0 .../app/views/cdr_signal/form_add.jst.eco | 0 .../app/views/cdr_signal/form_edit.jst.eco | 0 .../app/views/cdr_signal/index.jst.eco | 0 .../app/views/cdr_voice/form_add.jst.eco | 0 .../app/views/cdr_voice/form_edit.jst.eco | 0 .../app/views/cdr_voice/index.jst.eco | 0 .../app/views/cdr_whatsapp/form_add.jst.eco | 0 .../app/views/cdr_whatsapp/form_edit.jst.eco | 0 .../app/views/cdr_whatsapp/index.jst.eco | 0 .../views/generic/notification_matrix.jst.eco | 0 .../app/views/profile/notification.jst.eco | 0 .../assets/stylesheets/addons/cdr_signal.css | 0 .../stylesheets/addons/cdr_whatsapp.css | 0 .../cdr_signal_channels_controller.rb | 0 .../cdr_ticket_article_types_controller.rb | 0 .../channels_cdr_signal_controller.rb | 0 .../channels_cdr_voice_controller.rb | 0 .../channels_cdr_whatsapp_controller.rb | 40 +- .../app/controllers/formstack_controller.rb | 39 + .../app/controllers/opensearch_controller.rb | 19 + .../TicketDetailView/ArticleReply.vue | 0 .../article-type/plugins/signalMessage.ts | 0 .../article-type/plugins/whatsappMessage.ts | 0 .../action/plugins/cdr_signal.ts | 0 .../action/plugins/cdr_whatsapp.ts | 0 .../app/jobs/communicate_cdr_signal_job.rb | 0 .../app/jobs/communicate_cdr_whatsapp_job.rb | 0 .../app/jobs/create_ticket_from_form_job.rb | 319 +++++++ .../src/app/jobs/signal_notification_job.rb | 0 .../app/models/channel/driver/cdr_signal.rb | 0 .../app/models/channel/driver/cdr_whatsapp.rb | 0 .../models/link/setup_split_signal_group.rb | 0 .../enqueue_communicate_cdr_signal_job.rb | 0 .../enqueue_communicate_cdr_whatsapp_job.rb | 0 .../models/transaction/signal_notification.rb | 0 .../cdr_signal_channels_controller_policy.rb | 0 ..._ticket_article_types_controller_policy.rb | 0 .../channels_cdr_signal_controller_policy.rb | 0 .../channels_cdr_voice_controller_policy.rb | 0 ...channels_cdr_whatsapp_controller_policy.rb | 0 .../formstack_controller_policy.rb | 8 + .../opensearch_controller_policy.rb | 8 + .../ticket_create/en.txt.erb | 0 .../ticket_escalation/en.txt.erb | 0 .../ticket_reminder_reached/en.txt.erb | 0 .../ticket_update/en.txt.erb | 0 .../src/config/initializers/cdr_signal.rb | 0 .../src/config/initializers/cdr_whatsapp.rb | 0 .../config/initializers/signal_cli_config.rb | 12 + .../src/config/routes/cdr_signal_channels.rb | 0 .../config/routes/cdr_ticket_article_types.rb | 0 .../src/config/routes/channel_cdr_signal.rb | 0 .../src/config/routes/channel_cdr_voice.rb | 0 .../src/config/routes/channel_cdr_whatsapp.rb | 1 + .../src/config/routes/formstack.rb | 7 + .../src/config/routes/opensearch.rb | 7 + ...0200211123028_hardening_harden_settings.rb | 0 .../20210525091356_cdr_signal_channel.rb | 0 .../link}/20210525091357_cdr_voice_channel.rb | 0 .../20210525091358_cdr_whatsapp_channel.rb | 0 ...5000001_add_channel_restriction_setting.rb | 0 ...250105000002_enable_desktop_beta_switch.rb | 0 .../20250105000003_add_cdr_link_config.rb | 0 .../20260115000001_add_messaging_user_ids.rb | 0 ...000001_add_signal_notification_settings.rb | 0 .../20260210000001_add_signal_schedulers.rb | 34 + .../20260210000002_add_formstack_settings.rb | 60 ++ .../20260210000003_add_opensearch_settings.rb | 63 ++ .../src/lib/cdr_signal.rb | 113 ++- .../src/lib/cdr_signal_api.rb | 156 ++++ .../src/lib/cdr_signal_poller.rb | 428 +++++++++ .../src/lib/cdr_whatsapp.rb | 0 .../src/lib/cdr_whatsapp_api.rb | 84 ++ .../src/lib/signal_notification_sender.rb | 13 +- .../public/assets/images/icons/cdr_signal.svg | 0 .../assets/images/icons/cdr_whatsapp.svg | 0 pnpm-lock.yaml | 232 +---- turbo.json | 18 +- 444 files changed, 1485 insertions(+), 21978 deletions(-) delete mode 100644 apps/bridge-frontend/.eslintrc.json delete mode 100644 apps/bridge-frontend/.gitignore delete mode 100644 apps/bridge-frontend/Dockerfile delete mode 100644 apps/bridge-frontend/README.md delete mode 100644 apps/bridge-frontend/app/(login)/login/page.tsx delete mode 100644 apps/bridge-frontend/app/(main)/[...segment]/@create/page.tsx delete mode 100644 apps/bridge-frontend/app/(main)/[...segment]/@detail/page.tsx delete mode 100644 apps/bridge-frontend/app/(main)/[...segment]/@edit/page.tsx delete mode 100644 apps/bridge-frontend/app/(main)/[...segment]/layout.tsx delete mode 100644 apps/bridge-frontend/app/(main)/[...segment]/page.tsx delete mode 100644 apps/bridge-frontend/app/(main)/layout.tsx delete mode 100644 apps/bridge-frontend/app/(main)/page.tsx delete mode 100644 apps/bridge-frontend/app/_components/InternalLayout.tsx delete mode 100644 apps/bridge-frontend/app/_components/Login.tsx delete mode 100644 apps/bridge-frontend/app/_components/Sidebar.tsx delete mode 100644 apps/bridge-frontend/app/_images/link-logo-small.png delete mode 100644 apps/bridge-frontend/app/_lib/authentication.ts delete mode 100644 apps/bridge-frontend/app/api/[service]/bots/[token]/receive/route.ts delete mode 100644 apps/bridge-frontend/app/api/[service]/bots/[token]/relink/route.ts delete mode 100644 apps/bridge-frontend/app/api/[service]/bots/[token]/route.ts delete mode 100644 apps/bridge-frontend/app/api/[service]/bots/[token]/send/route.ts delete mode 100644 apps/bridge-frontend/app/api/[service]/webhooks/route.ts delete mode 100644 apps/bridge-frontend/app/api/auth/[...nextauth]/route.ts delete mode 100644 apps/bridge-frontend/app/layout.tsx delete mode 100644 apps/bridge-frontend/docker-entrypoint.sh delete mode 100644 apps/bridge-frontend/middleware.ts delete mode 100644 apps/bridge-frontend/next.config.js delete mode 100644 apps/bridge-frontend/package.json delete mode 100644 apps/bridge-frontend/public/robots.txt delete mode 100644 apps/bridge-frontend/tsconfig.json delete mode 100644 apps/bridge-migrations/README.md delete mode 100644 apps/bridge-migrations/migrate.ts delete mode 100644 apps/bridge-migrations/migrations/0001-add-next-auth.ts delete mode 100644 apps/bridge-migrations/migrations/0002-add-signal.ts delete mode 100644 apps/bridge-migrations/migrations/0003-add-whatsapp.ts delete mode 100644 apps/bridge-migrations/migrations/0004-add-voice.ts delete mode 100644 apps/bridge-migrations/migrations/0005-add-facebook.ts delete mode 100644 apps/bridge-migrations/migrations/0006-add-webhooks.ts delete mode 100644 apps/bridge-migrations/migrations/0007-add-settings.ts delete mode 100644 apps/bridge-migrations/migrations/0008-add-user-role.ts delete mode 100644 apps/bridge-migrations/package.json rename {packages/bridge-common/lib/config => apps/bridge-whatsapp/src}/attachments.ts (100%) rename packages/logger/src/config.ts => apps/bridge-whatsapp/src/lib/logger.ts (69%) delete mode 100644 apps/bridge-worker/.dockerignore delete mode 100644 apps/bridge-worker/Dockerfile delete mode 100644 apps/bridge-worker/README.md delete mode 100644 apps/bridge-worker/crontab delete mode 100644 apps/bridge-worker/docker-entrypoint.sh delete mode 100644 apps/bridge-worker/graphile.config.ts delete mode 100644 apps/bridge-worker/index.ts delete mode 100644 apps/bridge-worker/lib/common.ts delete mode 100644 apps/bridge-worker/lib/db.ts delete mode 100644 apps/bridge-worker/lib/facebook.ts delete mode 100644 apps/bridge-worker/lib/formstack-field-mapping.ts delete mode 100644 apps/bridge-worker/lib/media-convert.ts delete mode 100644 apps/bridge-worker/lib/tag-map.ts delete mode 100644 apps/bridge-worker/lib/utils.ts delete mode 100644 apps/bridge-worker/lib/voice.ts delete mode 100644 apps/bridge-worker/lib/whatsapp.ts delete mode 100644 apps/bridge-worker/lib/zammad.ts delete mode 100644 apps/bridge-worker/package.json delete mode 100644 apps/bridge-worker/tasks/check-group-membership.ts delete mode 100644 apps/bridge-worker/tasks/common/notify-webhooks.ts delete mode 100644 apps/bridge-worker/tasks/facebook/receive-facebook-message.ts delete mode 100644 apps/bridge-worker/tasks/facebook/send-facebook-message.ts delete mode 100644 apps/bridge-worker/tasks/fetch-signal-messages.ts delete mode 100644 apps/bridge-worker/tasks/formstack/create-ticket-from-form.ts delete mode 100644 apps/bridge-worker/tasks/signal/receive-signal-message.ts delete mode 100644 apps/bridge-worker/tasks/signal/send-signal-message.ts delete mode 100644 apps/bridge-worker/tasks/voice/receive-voice-message.ts delete mode 100644 apps/bridge-worker/tasks/voice/send-voice-message.ts delete mode 100644 apps/bridge-worker/tasks/voice/twilio-recording.ts delete mode 100644 apps/bridge-worker/tasks/voice/voice-line-audio-update.ts delete mode 100644 apps/bridge-worker/tasks/voice/voice-line-delete.ts delete mode 100644 apps/bridge-worker/tasks/voice/voice-line-provider-update.ts delete mode 100644 apps/bridge-worker/tasks/whatsapp/receive-whatsapp-message.ts delete mode 100644 apps/bridge-worker/tasks/whatsapp/send-whatsapp-message.ts delete mode 100644 apps/bridge-worker/tsconfig.json delete mode 100644 apps/link/.dockerignore delete mode 100644 apps/link/.gitignore delete mode 100644 apps/link/Dockerfile delete mode 100644 apps/link/LICENSE.md delete mode 100644 apps/link/README.md delete mode 100644 apps/link/app/(login)/login/_components/Login.tsx delete mode 100644 apps/link/app/(login)/login/page.tsx delete mode 100644 apps/link/app/(main)/_components/ClientOnly.tsx delete mode 100644 apps/link/app/(main)/_components/DefaultDashboard.tsx delete mode 100644 apps/link/app/(main)/_components/InternalLayout.tsx delete mode 100644 apps/link/app/(main)/_components/SearchBox.tsx delete mode 100644 apps/link/app/(main)/_components/SetupModeWarning.tsx delete mode 100644 apps/link/app/(main)/_components/Sidebar.tsx delete mode 100644 apps/link/app/(main)/_components/StyledDataGrid.tsx delete mode 100644 apps/link/app/(main)/_components/ZammadWrapper.tsx delete mode 100644 apps/link/app/(main)/admin/bridge/[...segment]/@create/page.tsx delete mode 100644 apps/link/app/(main)/admin/bridge/[...segment]/@detail/page.tsx delete mode 100644 apps/link/app/(main)/admin/bridge/[...segment]/@edit/page.tsx delete mode 100644 apps/link/app/(main)/admin/bridge/[...segment]/layout.tsx delete mode 100644 apps/link/app/(main)/admin/bridge/[...segment]/page.tsx delete mode 100644 apps/link/app/(main)/admin/bridge/page.tsx delete mode 100644 apps/link/app/(main)/admin/opensearch/page.tsx delete mode 100644 apps/link/app/(main)/docs/_components/DocsWrapper.tsx delete mode 100644 apps/link/app/(main)/docs/page.tsx delete mode 100644 apps/link/app/(main)/layout.tsx delete mode 100644 apps/link/app/(main)/logout/page.tsx delete mode 100644 apps/link/app/(main)/page.tsx delete mode 100644 apps/link/app/(main)/setup/_components/Setup.tsx delete mode 100644 apps/link/app/(main)/setup/page.tsx delete mode 100644 apps/link/app/_actions/groups.ts delete mode 100644 apps/link/app/_actions/search.ts delete mode 100644 apps/link/app/_actions/tickets.ts delete mode 100644 apps/link/app/_actions/users.ts delete mode 100644 apps/link/app/_components/Button.tsx delete mode 100644 apps/link/app/_components/DisplayError.tsx delete mode 100644 apps/link/app/_components/MultiProvider.tsx delete mode 100644 apps/link/app/_components/OpenSearchWrapper.tsx delete mode 100644 apps/link/app/_components/ZammadLoginProvider.tsx delete mode 100644 apps/link/app/_graphql/createTicketMutation.ts delete mode 100644 apps/link/app/_graphql/getTicketArticlesQuery.ts delete mode 100644 apps/link/app/_graphql/getTicketOverviewCountsQuery.ts delete mode 100644 apps/link/app/_graphql/getTicketQuery.ts delete mode 100644 apps/link/app/_graphql/searchQuery.ts delete mode 100644 apps/link/app/_graphql/updateTagsMutation.ts delete mode 100644 apps/link/app/_graphql/updateTicketMutation.ts delete mode 100644 apps/link/app/_lib/authentication.ts delete mode 100644 apps/link/app/_lib/zammad.ts delete mode 100644 apps/link/app/_styles/global.css delete mode 100644 apps/link/app/api/[service]/bots/[token]/receive/route.ts delete mode 100644 apps/link/app/api/[service]/bots/[token]/relink/route.ts delete mode 100644 apps/link/app/api/[service]/bots/[token]/route.ts delete mode 100644 apps/link/app/api/[service]/bots/[token]/send/route.ts delete mode 100644 apps/link/app/api/[service]/webhooks/route.ts delete mode 100644 apps/link/app/api/auth/[...nextauth]/route.ts delete mode 100644 apps/link/app/api/formstack/route.ts delete mode 100644 apps/link/app/api/logout/route.ts delete mode 100644 apps/link/app/api/v2/users/route.ts delete mode 100644 apps/link/app/error.tsx delete mode 100644 apps/link/app/layout.tsx delete mode 100644 apps/link/docker-entrypoint.sh delete mode 100644 apps/link/middleware.ts delete mode 100644 apps/link/next-env.d.ts delete mode 100644 apps/link/next.config.js delete mode 100644 apps/link/package.json delete mode 100644 apps/link/public/link-logo-small.png delete mode 100644 apps/link/public/robots.txt delete mode 100644 apps/link/public/silence.mp3 delete mode 100644 apps/link/tsconfig.json delete mode 100644 docker/compose/bridge.yml delete mode 100644 docker/compose/link.yml delete mode 100644 packages/bridge-common/index.ts delete mode 100644 packages/bridge-common/lib/config/signal.ts delete mode 100644 packages/bridge-common/lib/database.ts delete mode 100644 packages/bridge-common/lib/utils.ts delete mode 100644 packages/bridge-common/package.json delete mode 100644 packages/bridge-common/tsconfig.json delete mode 100644 packages/bridge-ui/actions/service.ts delete mode 100644 packages/bridge-ui/components/Create.tsx delete mode 100644 packages/bridge-ui/components/DeleteDialog.tsx delete mode 100644 packages/bridge-ui/components/Detail.tsx delete mode 100644 packages/bridge-ui/components/Edit.tsx delete mode 100644 packages/bridge-ui/components/Home.tsx delete mode 100644 packages/bridge-ui/components/List.tsx delete mode 100644 packages/bridge-ui/components/QRCode.tsx delete mode 100644 packages/bridge-ui/components/ServiceLayout.tsx delete mode 100644 packages/bridge-ui/config/config.ts delete mode 100644 packages/bridge-ui/config/facebook.ts delete mode 100644 packages/bridge-ui/config/signal.ts delete mode 100644 packages/bridge-ui/config/users.ts delete mode 100644 packages/bridge-ui/config/voice.ts delete mode 100644 packages/bridge-ui/config/webhooks.ts delete mode 100644 packages/bridge-ui/config/whatsapp.ts delete mode 100644 packages/bridge-ui/images.d.ts delete mode 100644 packages/bridge-ui/index.ts delete mode 100644 packages/bridge-ui/lib/actions.ts delete mode 100644 packages/bridge-ui/lib/facebook.ts delete mode 100644 packages/bridge-ui/lib/frontendUtils.ts delete mode 100644 packages/bridge-ui/lib/routing.ts delete mode 100644 packages/bridge-ui/lib/service.ts delete mode 100644 packages/bridge-ui/lib/signal.ts delete mode 100644 packages/bridge-ui/lib/utils.ts delete mode 100644 packages/bridge-ui/lib/voice.ts delete mode 100644 packages/bridge-ui/lib/whatsapp.ts delete mode 100644 packages/bridge-ui/package.json delete mode 100644 packages/bridge-ui/styles/theme.ts delete mode 100644 packages/bridge-ui/tsconfig.json delete mode 100644 packages/eslint-config/CHANGELOG.md delete mode 100644 packages/eslint-config/LICENSE.md delete mode 100644 packages/eslint-config/README.md delete mode 100644 packages/eslint-config/index.js delete mode 100644 packages/eslint-config/package.json delete mode 100644 packages/eslint-config/patch/modern-module-resolution.js delete mode 100644 packages/eslint-config/profile/browser.js delete mode 100644 packages/eslint-config/profile/common.js delete mode 100644 packages/eslint-config/profile/cypress.js delete mode 100644 packages/eslint-config/profile/jest.js delete mode 100644 packages/eslint-config/profile/node.js delete mode 100644 packages/eslint-config/profile/typescript.js delete mode 100644 packages/jest-config/index.js delete mode 100644 packages/jest-config/jest-preset.js delete mode 100644 packages/jest-config/package.json delete mode 100644 packages/logger/package.json delete mode 100644 packages/logger/src/index.ts delete mode 100644 packages/logger/tsconfig.json delete mode 100644 packages/signal-api/.eslintrc.js delete mode 100644 packages/signal-api/.openapi-generator-ignore delete mode 100644 packages/signal-api/apis/AccountsApi.ts delete mode 100644 packages/signal-api/apis/AttachmentsApi.ts delete mode 100644 packages/signal-api/apis/ContactsApi.ts delete mode 100644 packages/signal-api/apis/DevicesApi.ts delete mode 100644 packages/signal-api/apis/GeneralApi.ts delete mode 100644 packages/signal-api/apis/GroupsApi.ts delete mode 100644 packages/signal-api/apis/IdentitiesApi.ts delete mode 100644 packages/signal-api/apis/MessagesApi.ts delete mode 100644 packages/signal-api/apis/ProfilesApi.ts delete mode 100644 packages/signal-api/apis/ReactionsApi.ts delete mode 100644 packages/signal-api/apis/ReceiptsApi.ts delete mode 100644 packages/signal-api/apis/SearchApi.ts delete mode 100644 packages/signal-api/apis/StickerPacksApi.ts delete mode 100644 packages/signal-api/apis/index.ts delete mode 100644 packages/signal-api/index.ts delete mode 100644 packages/signal-api/models/ApiAddDeviceRequest.ts delete mode 100644 packages/signal-api/models/ApiAddStickerPackRequest.ts delete mode 100644 packages/signal-api/models/ApiChangeGroupAdminsRequest.ts delete mode 100644 packages/signal-api/models/ApiChangeGroupMembersRequest.ts delete mode 100644 packages/signal-api/models/ApiConfiguration.ts delete mode 100644 packages/signal-api/models/ApiCreateGroupRequest.ts delete mode 100644 packages/signal-api/models/ApiCreateGroupResponse.ts delete mode 100644 packages/signal-api/models/ApiError.ts delete mode 100644 packages/signal-api/models/ApiGroupPermissions.ts delete mode 100644 packages/signal-api/models/ApiLoggingConfiguration.ts delete mode 100644 packages/signal-api/models/ApiRateLimitChallengeRequest.ts delete mode 100644 packages/signal-api/models/ApiReaction.ts delete mode 100644 packages/signal-api/models/ApiReceipt.ts delete mode 100644 packages/signal-api/models/ApiRegisterNumberRequest.ts delete mode 100644 packages/signal-api/models/ApiSearchResponse.ts delete mode 100644 packages/signal-api/models/ApiSendMessageError.ts delete mode 100644 packages/signal-api/models/ApiSendMessageResponse.ts delete mode 100644 packages/signal-api/models/ApiSendMessageV1.ts delete mode 100644 packages/signal-api/models/ApiSendMessageV2.ts delete mode 100644 packages/signal-api/models/ApiSetUsernameRequest.ts delete mode 100644 packages/signal-api/models/ApiTrustIdentityRequest.ts delete mode 100644 packages/signal-api/models/ApiTrustModeRequest.ts delete mode 100644 packages/signal-api/models/ApiTrustModeResponse.ts delete mode 100644 packages/signal-api/models/ApiTypingIndicatorRequest.ts delete mode 100644 packages/signal-api/models/ApiUnregisterNumberRequest.ts delete mode 100644 packages/signal-api/models/ApiUpdateAccountSettingsRequest.ts delete mode 100644 packages/signal-api/models/ApiUpdateContactRequest.ts delete mode 100644 packages/signal-api/models/ApiUpdateGroupRequest.ts delete mode 100644 packages/signal-api/models/ApiUpdateProfileRequest.ts delete mode 100644 packages/signal-api/models/ApiVerifyNumberSettings.ts delete mode 100644 packages/signal-api/models/ClientAbout.ts delete mode 100644 packages/signal-api/models/ClientGroupEntry.ts delete mode 100644 packages/signal-api/models/ClientIdentityEntry.ts delete mode 100644 packages/signal-api/models/ClientListInstalledStickerPacksResponse.ts delete mode 100644 packages/signal-api/models/ClientSetUsernameResponse.ts delete mode 100644 packages/signal-api/models/index.ts delete mode 100644 packages/signal-api/openapitools.json delete mode 100644 packages/signal-api/package.json delete mode 100644 packages/signal-api/runtime.ts delete mode 100644 packages/signal-api/tsconfig.json delete mode 100644 packages/typescript-config/CHANGELOG.md delete mode 100644 packages/typescript-config/LICENSE.md delete mode 100644 packages/typescript-config/README.md delete mode 100644 packages/typescript-config/index.js delete mode 100644 packages/typescript-config/package.json delete mode 100644 packages/typescript-config/tsconfig.json delete mode 100644 packages/typescript-config/tsconfig.next.json delete mode 100644 packages/typescript-config/tsconfig.node.json delete mode 100644 packages/ui/components/Autocomplete.tsx delete mode 100644 packages/ui/components/Button.tsx delete mode 100644 packages/ui/components/Detail.tsx delete mode 100644 packages/ui/components/Dialog.tsx delete mode 100644 packages/ui/components/DisplayTextField.tsx delete mode 100644 packages/ui/components/List.tsx delete mode 100644 packages/ui/components/MultiValueField.tsx delete mode 100644 packages/ui/components/Select.tsx delete mode 100644 packages/ui/components/Sidebar.tsx delete mode 100644 packages/ui/components/SidebarItem.tsx delete mode 100644 packages/ui/components/TextField.tsx delete mode 100644 packages/ui/index.ts delete mode 100644 packages/ui/package.json delete mode 100644 packages/ui/styles/theme.ts delete mode 100644 packages/ui/tsconfig.json delete mode 100644 packages/zammad-addon-bridge/package.json delete mode 100644 packages/zammad-addon-bridge/src/lib/cdr_signal_api.rb delete mode 100644 packages/zammad-addon-bridge/src/lib/cdr_whatsapp_api.rb delete mode 100644 packages/zammad-addon-bridge/turbo.json delete mode 100644 packages/zammad-addon-common/package.json delete mode 100644 packages/zammad-addon-common/tsconfig.json delete mode 100644 packages/zammad-addon-hardening/README.md delete mode 100644 packages/zammad-addon-hardening/package.json delete mode 100644 packages/zammad-addon-hardening/src/.ruby-version delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/cs.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/de.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/en.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/es.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/fr.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/it.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/pl.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/pt-br.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/zh-cn.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_create/zh-tw.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/cs.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/de.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/en.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/es.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/fr.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/it.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/pl.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/pt-br.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/zh-cn.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation/zh-tw.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/cs.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/de.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/en.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/es.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/fr.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/it.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/pl.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/pt-br.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/zh-cn.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_escalation_warning/zh-tw.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/cs.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/de.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/en.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/es.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/fr.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/it.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/pt-br.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/zh-cn.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_reminder_reached/zh-tw.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/cs.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/de.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/en.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/es.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/fr.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/it.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/pt-br.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/zh-cn.html.erb delete mode 100644 packages/zammad-addon-hardening/src/app/views/mailer/ticket_update/zh-tw.html.erb delete mode 100644 packages/zammad-addon-hardening/src/db/addon/hardening/.gitkeep delete mode 100644 packages/zammad-addon-hardening/turbo.json rename packages/{zammad-addon-bridge => zammad-addon-link}/README.md (91%) create mode 100644 packages/zammad-addon-link/package.json rename packages/{zammad-addon-common => zammad-addon-link/scripts}/build.ts (82%) rename packages/{zammad-addon-common => zammad-addon-link/scripts}/migrate.ts (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/.ruby-version (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/controllers/_channel/cdr_signal.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/controllers/_channel/cdr_voice.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/controllers/_channel/cdr_whatsapp.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/controllers/_profile/notification.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/controllers/ticket_zoom/article_action/cdr_link_channel_filter.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/controllers/ticket_zoom/article_action/cdr_signal.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/controllers/ticket_zoom/article_action/cdr_whatsapp.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_signal/form_add.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_signal/form_edit.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_signal/index.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_voice/form_add.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_voice/form_edit.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_voice/index.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_whatsapp/form_add.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_whatsapp/form_edit.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/cdr_whatsapp/index.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/generic/notification_matrix.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/javascripts/app/views/profile/notification.jst.eco (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/stylesheets/addons/cdr_signal.css (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/assets/stylesheets/addons/cdr_whatsapp.css (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/controllers/cdr_signal_channels_controller.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/controllers/cdr_ticket_article_types_controller.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/controllers/channels_cdr_signal_controller.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/controllers/channels_cdr_voice_controller.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/controllers/channels_cdr_whatsapp_controller.rb (87%) create mode 100644 packages/zammad-addon-link/src/app/controllers/formstack_controller.rb create mode 100644 packages/zammad-addon-link/src/app/controllers/opensearch_controller.rb rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/ArticleReply.vue (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/article-type/plugins/signalMessage.ts (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/article-type/plugins/whatsappMessage.ts (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/frontend/shared/entities/ticket-article/action/plugins/cdr_signal.ts (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/frontend/shared/entities/ticket-article/action/plugins/cdr_whatsapp.ts (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/jobs/communicate_cdr_signal_job.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/jobs/communicate_cdr_whatsapp_job.rb (100%) create mode 100644 packages/zammad-addon-link/src/app/jobs/create_ticket_from_form_job.rb rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/jobs/signal_notification_job.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/models/channel/driver/cdr_signal.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/models/channel/driver/cdr_whatsapp.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/models/link/setup_split_signal_group.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/models/ticket/article/enqueue_communicate_cdr_signal_job.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/models/ticket/article/enqueue_communicate_cdr_whatsapp_job.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/models/transaction/signal_notification.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/policies/controllers/cdr_signal_channels_controller_policy.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/policies/controllers/cdr_ticket_article_types_controller_policy.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/policies/controllers/channels_cdr_signal_controller_policy.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/policies/controllers/channels_cdr_voice_controller_policy.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/policies/controllers/channels_cdr_whatsapp_controller_policy.rb (100%) create mode 100644 packages/zammad-addon-link/src/app/policies/controllers/formstack_controller_policy.rb create mode 100644 packages/zammad-addon-link/src/app/policies/controllers/opensearch_controller_policy.rb rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/views/signal_notification/ticket_create/en.txt.erb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/views/signal_notification/ticket_escalation/en.txt.erb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/views/signal_notification/ticket_reminder_reached/en.txt.erb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/app/views/signal_notification/ticket_update/en.txt.erb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/config/initializers/cdr_signal.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/config/initializers/cdr_whatsapp.rb (100%) create mode 100644 packages/zammad-addon-link/src/config/initializers/signal_cli_config.rb rename packages/{zammad-addon-bridge => zammad-addon-link}/src/config/routes/cdr_signal_channels.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/config/routes/cdr_ticket_article_types.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/config/routes/channel_cdr_signal.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/config/routes/channel_cdr_voice.rb (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/config/routes/channel_cdr_whatsapp.rb (88%) create mode 100644 packages/zammad-addon-link/src/config/routes/formstack.rb create mode 100644 packages/zammad-addon-link/src/config/routes/opensearch.rb rename packages/{zammad-addon-hardening/src/db/addon/hardening => zammad-addon-link/src/db/addon/link}/20200211123028_hardening_harden_settings.rb (100%) rename packages/{zammad-addon-bridge/src/db/addon/bridge => zammad-addon-link/src/db/addon/link}/20210525091356_cdr_signal_channel.rb (100%) rename packages/{zammad-addon-bridge/src/db/addon/bridge => zammad-addon-link/src/db/addon/link}/20210525091357_cdr_voice_channel.rb (100%) rename packages/{zammad-addon-bridge/src/db/addon/bridge => zammad-addon-link/src/db/addon/link}/20210525091358_cdr_whatsapp_channel.rb (100%) rename packages/{zammad-addon-bridge/src/db/addon/bridge => zammad-addon-link/src/db/addon/link}/20250105000001_add_channel_restriction_setting.rb (100%) rename packages/{zammad-addon-bridge/src/db/addon/bridge => zammad-addon-link/src/db/addon/link}/20250105000002_enable_desktop_beta_switch.rb (100%) rename packages/{zammad-addon-bridge/src/db/addon/bridge => zammad-addon-link/src/db/addon/link}/20250105000003_add_cdr_link_config.rb (100%) rename packages/{zammad-addon-bridge/src/db/addon/bridge => zammad-addon-link/src/db/addon/link}/20260115000001_add_messaging_user_ids.rb (100%) rename packages/{zammad-addon-bridge/src/db/addon/bridge => zammad-addon-link/src/db/addon/link}/20260120000001_add_signal_notification_settings.rb (100%) create mode 100644 packages/zammad-addon-link/src/db/addon/link/20260210000001_add_signal_schedulers.rb create mode 100644 packages/zammad-addon-link/src/db/addon/link/20260210000002_add_formstack_settings.rb create mode 100644 packages/zammad-addon-link/src/db/addon/link/20260210000003_add_opensearch_settings.rb rename packages/{zammad-addon-bridge => zammad-addon-link}/src/lib/cdr_signal.rb (71%) create mode 100644 packages/zammad-addon-link/src/lib/cdr_signal_api.rb create mode 100644 packages/zammad-addon-link/src/lib/cdr_signal_poller.rb rename packages/{zammad-addon-bridge => zammad-addon-link}/src/lib/cdr_whatsapp.rb (100%) create mode 100644 packages/zammad-addon-link/src/lib/cdr_whatsapp_api.rb rename packages/{zammad-addon-bridge => zammad-addon-link}/src/lib/signal_notification_sender.rb (89%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/public/assets/images/icons/cdr_signal.svg (100%) rename packages/{zammad-addon-bridge => zammad-addon-link}/src/public/assets/images/icons/cdr_whatsapp.svg (100%) diff --git a/.gitignore b/.gitignore index 1f5a509..2bea406 100644 --- a/.gitignore +++ b/.gitignore @@ -28,8 +28,7 @@ baileys-state signald-state project.org **/.openapi-generator/ -apps/bridge-worker/scripts/* ENVIRONMENT_VARIABLES_MIGRATION.md local-scripts/* docs/ -packages/zammad-addon-bridge/test/ +packages/zammad-addon-link/test/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8fcd82b..0711bc2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -69,39 +69,6 @@ buildx-docker-release: variables: DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/buildx -link-docker-build: - extends: .docker-build - variables: - DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/link - DOCKERFILE_PATH: ./apps/link/Dockerfile - -link-docker-release: - extends: .docker-release - variables: - DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/link - -bridge-frontend-docker-build: - extends: .docker-build - variables: - DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge-frontend - DOCKERFILE_PATH: ./apps/bridge-frontend/Dockerfile - -bridge-frontend-docker-release: - extends: .docker-release - variables: - DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge-frontend - -bridge-worker-docker-build: - extends: .docker-build - variables: - DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge-worker - DOCKERFILE_PATH: ./apps/bridge-worker/Dockerfile - -bridge-worker-docker-release: - extends: .docker-release - variables: - DOCKER_NS: ${CI_REGISTRY}/digiresilience/link/link-stack/bridge-worker - bridge-whatsapp-docker-build: extends: .docker-build variables: diff --git a/apps/bridge-frontend/.eslintrc.json b/apps/bridge-frontend/.eslintrc.json deleted file mode 100644 index bffb357..0000000 --- a/apps/bridge-frontend/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/apps/bridge-frontend/.gitignore b/apps/bridge-frontend/.gitignore deleted file mode 100644 index fd3dbb5..0000000 --- a/apps/bridge-frontend/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/apps/bridge-frontend/Dockerfile b/apps/bridge-frontend/Dockerfile deleted file mode 100644 index 75a19ce..0000000 --- a/apps/bridge-frontend/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -FROM node:22-bookworm-slim AS base - -FROM base AS builder -ARG APP_DIR=/opt/bridge-frontend -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -RUN mkdir -p ${APP_DIR}/ -RUN corepack enable && corepack prepare pnpm@9.15.4 --activate -RUN pnpm add -g turbo -WORKDIR ${APP_DIR} -COPY . . -RUN turbo prune --scope=@link-stack/bridge-frontend --scope=@link-stack/bridge-migrations --docker - -FROM base AS installer -ARG APP_DIR=/opt/bridge-frontend -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -WORKDIR ${APP_DIR} -RUN corepack enable && corepack prepare pnpm@9.15.4 --activate -COPY --from=builder ${APP_DIR}/.gitignore .gitignore -COPY --from=builder ${APP_DIR}/out/json/ . -COPY --from=builder ${APP_DIR}/out/pnpm-lock.yaml ./pnpm-lock.yaml -RUN pnpm install --frozen-lockfile - -COPY --from=builder ${APP_DIR}/out/full/ . -RUN pnpm add -g turbo -RUN turbo run build --filter=@link-stack/bridge-frontend --filter=@link-stack/bridge-migrations - -FROM base AS runner -ARG APP_DIR=/opt/bridge-frontend -WORKDIR ${APP_DIR}/ -ARG BUILD_DATE -ARG VERSION -LABEL maintainer="Darren Clarke " -LABEL org.label-schema.build-date=$BUILD_DATE -LABEL org.label-schema.version=$VERSION -ENV APP_DIR ${APP_DIR} -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -RUN corepack enable && corepack prepare pnpm@9.15.4 --activate -RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ - apt-get install -y --no-install-recommends \ - dumb-init -RUN mkdir -p ${APP_DIR} -WORKDIR ${APP_DIR} -COPY --from=installer ${APP_DIR} ./ -RUN chown -R node:node ${APP_DIR}/ -WORKDIR ${APP_DIR}/apps/bridge-frontend/ -RUN chmod +x docker-entrypoint.sh -USER node -EXPOSE 3000 -ENV PORT 3000 -ENV NODE_ENV production -ENTRYPOINT ["/opt/bridge-frontend/apps/bridge-frontend/docker-entrypoint.sh"] diff --git a/apps/bridge-frontend/README.md b/apps/bridge-frontend/README.md deleted file mode 100644 index ebec248..0000000 --- a/apps/bridge-frontend/README.md +++ /dev/null @@ -1,133 +0,0 @@ -# Bridge Frontend - -Frontend application for managing communication bridges between various messaging platforms and the CDR Link system. - -## Overview - -Bridge Frontend provides a web interface for configuring and managing communication channels including Signal, WhatsApp, Facebook, and Voice integrations. It handles bot registration, webhook configuration, and channel settings. - -## Features - -- **Channel Management**: Configure Signal, WhatsApp, Facebook, and Voice channels -- **Bot Registration**: Register and manage bots for each communication platform -- **Webhook Configuration**: Set up webhooks for message routing -- **Settings Management**: Configure channel-specific settings and behaviors -- **User Authentication**: Secure access with NextAuth.js - -## Development - -### Prerequisites - -- Node.js >= 20 -- npm >= 10 -- PostgreSQL database -- Running bridge-worker service - -### Setup - -```bash -# Install dependencies -npm install - -# Run database migrations -npm run migrate:latest - -# Run development server -npm run dev - -# Build for production -npm run build - -# Start production server -npm run start -``` - -### Environment Variables - -Required environment variables: - -- `DATABASE_URL` - PostgreSQL connection string -- `DATABASE_HOST` - Database host -- `DATABASE_NAME` - Database name -- `DATABASE_USER` - Database username -- `DATABASE_PASSWORD` - Database password -- `NEXTAUTH_URL` - Application URL -- `NEXTAUTH_SECRET` - NextAuth.js secret -- `GOOGLE_CLIENT_ID` - Google OAuth client ID -- `GOOGLE_CLIENT_SECRET` - Google OAuth client secret - -### Available Scripts - -- `npm run dev` - Start development server -- `npm run build` - Build for production -- `npm run start` - Start production server -- `npm run lint` - Run ESLint -- `npm run migrate:latest` - Run all pending migrations -- `npm run migrate:down` - Rollback last migration -- `npm run migrate:up` - Run next migration -- `npm run migrate:make` - Create new migration - -## Architecture - -### Database Schema - -The application manages the following main entities: - -- **Bots**: Communication channel bot configurations -- **Webhooks**: Webhook endpoints for external integrations -- **Settings**: Channel-specific configuration settings -- **Users**: User accounts with role-based permissions - -### API Routes - -- `/api/auth` - Authentication endpoints -- `/api/[service]/bots` - Bot management for each service -- `/api/[service]/webhooks` - Webhook configuration - -### Page Structure - -- `/` - Dashboard/home page -- `/login` - Authentication page -- `/[...segment]` - Dynamic routing for CRUD operations - - `@create` - Create new entities - - `@detail` - View entity details - - `@edit` - Edit existing entities - -## Integration - -### Database Access - -Uses Kysely ORM for type-safe database queries: - -```typescript -import { db } from '@link-stack/database' - -const bots = await db - .selectFrom('bots') - .selectAll() - .execute() -``` - -### Authentication - -Integrated with NextAuth.js using database adapter: - -```typescript -import { authOptions } from '@link-stack/auth' -``` - -## Docker Support - -```bash -# Build image -docker build -t link-stack/bridge-frontend . - -# Run with docker-compose -docker-compose -f docker/compose/bridge.yml up -``` - -## Related Services - -- **bridge-worker**: Processes messages from configured channels -- **bridge-whatsapp**: WhatsApp-specific integration service -- **bridge-migrations**: Database schema management \ No newline at end of file diff --git a/apps/bridge-frontend/app/(login)/login/page.tsx b/apps/bridge-frontend/app/(login)/login/page.tsx deleted file mode 100644 index 8f79c27..0000000 --- a/apps/bridge-frontend/app/(login)/login/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Metadata } from "next"; -import { getSession } from "next-auth/react"; -import { Login } from "@/app/_components/Login"; - -export const dynamic = "force-dynamic"; - -export const metadata: Metadata = { - title: "Login", -}; - -export default async function Page() { - const session = await getSession(); - return ; -} diff --git a/apps/bridge-frontend/app/(main)/[...segment]/@create/page.tsx b/apps/bridge-frontend/app/(main)/[...segment]/@create/page.tsx deleted file mode 100644 index bc5b6b8..0000000 --- a/apps/bridge-frontend/app/(main)/[...segment]/@create/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Create } from "@link-stack/bridge-ui"; - -type PageProps = { - params: Promise<{ segment: string[] }>; -}; - -export default async function Page({ params }: PageProps) { - const { segment } = await params; - const service = segment[0]; - - return ; -} diff --git a/apps/bridge-frontend/app/(main)/[...segment]/@detail/page.tsx b/apps/bridge-frontend/app/(main)/[...segment]/@detail/page.tsx deleted file mode 100644 index e857b7d..0000000 --- a/apps/bridge-frontend/app/(main)/[...segment]/@detail/page.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { db } from "@link-stack/bridge-common"; -import { serviceConfig, Detail } from "@link-stack/bridge-ui"; - -type PageProps = { - params: Promise<{ segment: string[] }>; -}; - -export default async function Page({ params }: PageProps) { - const { segment } = await params; - const service = segment[0]; - const id = segment?.[1]; - - if (!id) return null; - - const { - [service]: { table }, - } = serviceConfig; - - const row = await db - .selectFrom(table) - .selectAll() - .where("id", "=", id) - .executeTakeFirst(); - - if (!row) return null; - - return ; -} diff --git a/apps/bridge-frontend/app/(main)/[...segment]/@edit/page.tsx b/apps/bridge-frontend/app/(main)/[...segment]/@edit/page.tsx deleted file mode 100644 index 82c8052..0000000 --- a/apps/bridge-frontend/app/(main)/[...segment]/@edit/page.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { db } from "@link-stack/bridge-common"; -import { serviceConfig, Edit } from "@link-stack/bridge-ui"; - -type PageProps = { - params: Promise<{ segment: string[] }>; -}; - -export default async function Page({ params }: PageProps) { - const { segment } = await params; - const service = segment[0]; - const id = segment?.[1]; - - if (!id) return null; - - const { - [service]: { table }, - } = serviceConfig; - - const row = await db - .selectFrom(table) - .selectAll() - .where("id", "=", id) - .executeTakeFirst(); - - if (!row) return null; - - return ; -} diff --git a/apps/bridge-frontend/app/(main)/[...segment]/layout.tsx b/apps/bridge-frontend/app/(main)/[...segment]/layout.tsx deleted file mode 100644 index c360a57..0000000 --- a/apps/bridge-frontend/app/(main)/[...segment]/layout.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { ServiceLayout } from "@link-stack/bridge-ui"; - -export default ServiceLayout; diff --git a/apps/bridge-frontend/app/(main)/[...segment]/page.tsx b/apps/bridge-frontend/app/(main)/[...segment]/page.tsx deleted file mode 100644 index 7b4fc03..0000000 --- a/apps/bridge-frontend/app/(main)/[...segment]/page.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { db } from "@link-stack/bridge-common"; -import { serviceConfig, List } from "@link-stack/bridge-ui"; - -type PageProps = { - params: Promise<{ - segment: string[]; - }>; -}; - -export default async function Page({ params }: PageProps) { - const { segment } = await params; - const service = segment[0]; - - if (!service) return null; - - const config = serviceConfig[service]; - - if (!config) return null; - - const rows = await db.selectFrom(config.table).selectAll().execute(); - - return ; -} diff --git a/apps/bridge-frontend/app/(main)/layout.tsx b/apps/bridge-frontend/app/(main)/layout.tsx deleted file mode 100644 index 32203a2..0000000 --- a/apps/bridge-frontend/app/(main)/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { InternalLayout } from "@/app/_components/InternalLayout"; - -export default function Layout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return {children}; -} diff --git a/apps/bridge-frontend/app/(main)/page.tsx b/apps/bridge-frontend/app/(main)/page.tsx deleted file mode 100644 index e01be47..0000000 --- a/apps/bridge-frontend/app/(main)/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Home } from "@link-stack/bridge-ui"; - -export default function Page() { - return ; -} diff --git a/apps/bridge-frontend/app/_components/InternalLayout.tsx b/apps/bridge-frontend/app/_components/InternalLayout.tsx deleted file mode 100644 index 72985ad..0000000 --- a/apps/bridge-frontend/app/_components/InternalLayout.tsx +++ /dev/null @@ -1,29 +0,0 @@ -"use client"; - -import { FC, PropsWithChildren, useState } from "react"; -import { Grid } from "@mui/material"; -import { CssBaseline } from "@mui/material"; -import { AppRouterCacheProvider } from "@mui/material-nextjs/v14-appRouter"; -import { SessionProvider } from "next-auth/react"; -import { Sidebar } from "./Sidebar"; - -export const InternalLayout: FC = ({ children }) => { - const [open, setOpen] = useState(true); - - return ( - - - - - - - {children as any} - - - - - ); -}; diff --git a/apps/bridge-frontend/app/_components/Login.tsx b/apps/bridge-frontend/app/_components/Login.tsx deleted file mode 100644 index 8e40129..0000000 --- a/apps/bridge-frontend/app/_components/Login.tsx +++ /dev/null @@ -1,185 +0,0 @@ -"use client"; - -import { FC, useState } from "react"; -import { - Box, - Grid, - Container, - IconButton, - Typography, - TextField, -} from "@mui/material"; -import { - Apple as AppleIcon, - Google as GoogleIcon, - Key as KeyIcon, -} from "@mui/icons-material"; -import { signIn } from "next-auth/react"; -import Image from "next/image"; -import LinkLogo from "@/app/_images/link-logo-small.png"; -import { colors, fonts } from "@link-stack/ui"; -import { useSearchParams } from "next/navigation"; - -type LoginProps = { - session: any; -}; - -export const Login: FC = ({ session }) => { - const origin = - typeof window !== "undefined" && window.location.origin - ? window.location.origin - : ""; - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const params = useSearchParams(); - const error = params.get("error"); - const { darkGray, cdrLinkOrange, white } = colors; - const { poppins } = fonts; - const buttonStyles = { - borderRadius: 500, - width: "100%", - fontSize: "16px", - fontWeight: "bold", - backgroundColor: white, - "&:hover": { - color: white, - backgroundColor: cdrLinkOrange, - }, - }; - const fieldStyles = { - "& label.Mui-focused": { - color: cdrLinkOrange, - }, - "& .MuiInput-underline:after": { - borderBottomColor: cdrLinkOrange, - }, - "& .MuiFilledInput-underline:after": { - borderBottomColor: cdrLinkOrange, - }, - "& .MuiOutlinedInput-root": { - "&.Mui-focused fieldset": { - borderColor: cdrLinkOrange, - }, - }, - }; - - return ( - - - - - - - Link logo - - - - - CDR Bridge - - - - - - {!session ? ( - - - {error ? ( - - - - {`${error} error`} - - - - ) : null} - - - signIn("google", { - callbackUrl: `${origin}`, - }) - } - > - - Sign in with Google - - - - - signIn("apple", { - callbackUrl: `${window.location.origin}`, - }) - } - > - - Sign in with Apple - - - - - ) : null} - {session ? ( - - {` ${session.user.name ?? session.user.email}.`} - - ) : null} - - - - - ); -}; diff --git a/apps/bridge-frontend/app/_components/Sidebar.tsx b/apps/bridge-frontend/app/_components/Sidebar.tsx deleted file mode 100644 index 31aaaaa..0000000 --- a/apps/bridge-frontend/app/_components/Sidebar.tsx +++ /dev/null @@ -1,399 +0,0 @@ -"use client"; - -import { FC } from "react"; -import { - Box, - Grid, - Typography, - List, - ListItemButton, - ListItemIcon, - ListItemText, - ListItemSecondaryAction, - Drawer, -} from "@mui/material"; -import { - ExpandCircleDown as ExpandCircleDownIcon, - AccountCircle as AccountCircleIcon, - Chat as ChatIcon, - PermPhoneMsg as PhoneIcon, - WhatsApp as WhatsAppIcon, - Facebook as FacebookIcon, - AirlineStops as AirlineStopsIcon, - Logout as LogoutIcon, -} from "@mui/icons-material"; -import { usePathname } from "next/navigation"; -import Link from "next/link"; -import Image from "next/image"; -import { typography, fonts, Button } from "@link-stack/ui"; -import LinkLogo from "@/app/_images/link-logo-small.png"; -import { useSession, signOut } from "next-auth/react"; - -const openWidth = 270; -const closedWidth = 70; - -const MenuItem = ({ - name, - href, - Icon, - iconSize, - inset = false, - selected = false, - open = true, - badge, - target = "_self", -}: any) => ( - - - {iconSize > 0 ? ( - - - - - - ) : ( - - - - - )} - {open && ( - - {name} - - } - /> - )} - {badge && badge > 0 ? ( - - - {badge} - - - ) : null} - - -); - -interface SidebarProps { - open: boolean; - setOpen: (open: boolean) => void; -} - -export const Sidebar: FC = ({ open, setOpen }) => { - const pathname = usePathname(); - const { poppins } = fonts; - const { bodyLarge } = typography; - const { data: session } = useSession(); - const user = session?.user; - - const logout = () => { - signOut({ callbackUrl: "/login" }); - }; - - return ( - - { - setOpen!(!open); - }} - > - - - - - - - Link logo - - . - - {open && ( - - - CDR Bridge - - - )} - - - - - - - - - - - - - - - - {user?.image && ( - - - Profile image - - - )} - - - - {user?.email} - - - -
}> - - - ); -} diff --git a/apps/link/app/(main)/_components/ClientOnly.tsx b/apps/link/app/(main)/_components/ClientOnly.tsx deleted file mode 100644 index b669b4f..0000000 --- a/apps/link/app/(main)/_components/ClientOnly.tsx +++ /dev/null @@ -1,15 +0,0 @@ -"use client"; - -import { ReactNode } from "react"; -import dynamic from "next/dynamic"; - -type ClientOnlyProps = { children: ReactNode }; -const ClientOnly = (props: ClientOnlyProps) => { - const { children } = props; - - return children; -}; - -export default dynamic(() => Promise.resolve(ClientOnly), { - ssr: false, -}); diff --git a/apps/link/app/(main)/_components/DefaultDashboard.tsx b/apps/link/app/(main)/_components/DefaultDashboard.tsx deleted file mode 100644 index 0150d9a..0000000 --- a/apps/link/app/(main)/_components/DefaultDashboard.tsx +++ /dev/null @@ -1,13 +0,0 @@ -"use client"; - -import { OpenSearchWrapper } from "@/app/_components/OpenSearchWrapper"; - -export function DefaultDashboard() { - // Extract just the URL path from the full dashboard URL - // The env var format is like: app/dashboards?security_tenant=global#/view/... - const defaultUrl = - process.env.NEXT_PUBLIC_OPENSEARCH_DEFAULT_DASHBOARD_URL || - "app/dashboards#/"; - - return ; -} diff --git a/apps/link/app/(main)/_components/InternalLayout.tsx b/apps/link/app/(main)/_components/InternalLayout.tsx deleted file mode 100644 index 6273bb4..0000000 --- a/apps/link/app/(main)/_components/InternalLayout.tsx +++ /dev/null @@ -1,35 +0,0 @@ -"use client"; - -import { FC, PropsWithChildren, useState } from "react"; -import { Grid, Box } from "@mui/material"; -import { Sidebar } from "./Sidebar"; -import { SetupModeWarning } from "./SetupModeWarning"; - -interface InternalLayoutProps extends PropsWithChildren { - setupModeActive: boolean; -} - -export const InternalLayout: FC = ({ - children, - setupModeActive, -}) => { - const [open, setOpen] = useState(true); - - return ( - - - - - - {children as any} - - - - ); -}; diff --git a/apps/link/app/(main)/_components/SearchBox.tsx b/apps/link/app/(main)/_components/SearchBox.tsx deleted file mode 100644 index 9f31c48..0000000 --- a/apps/link/app/(main)/_components/SearchBox.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import { FC, useState, useEffect } from "react"; -import { usePathname, useRouter } from "next/navigation"; -import { Grid, Box, TextField, Autocomplete } from "@mui/material"; -import { searchAllAction } from "@/app/_actions/search"; -import { colors } from "@link-stack/ui"; - -type SearchResultProps = { - props: any; - option: any; -}; - -const SearchInput = (params: any) => ( - -); - -const SearchResult: FC = ({ props, option }) => { - const { lightGrey, mediumGray, black, white } = colors; - - return ( - - - - - - {option.title} - - - - - - - {option.note} - - - - - - ); -}; - -export const SearchBox: FC = () => { - const [open, setOpen] = useState(false); - const [searchResults, setSearchResults] = useState([]); - const [selectedValue, setSelectedValue] = useState(null); - const [searchTerms, setSearchTerms] = useState(""); - const pathname = usePathname(); - const router = useRouter(); - - useEffect(() => { - const fetchSearchResults = async () => { - const results = await searchAllAction(searchTerms ?? "", 50); - setSearchResults(results); - }; - - fetchSearchResults(); - }, [searchTerms]); - - return ( - setOpen(false)} - inputValue={searchTerms} - onChange={(_event, option, reason) => { - if (!option) return; - const url = `/tickets/${option.internalId}`; - setSelectedValue(""); - router.push(url); - }} - onInputChange={(_event, value) => { - setSearchTerms(value); - }} - open={open} - onOpen={() => setOpen(true)} - noOptionsText="No results" - options={searchResults ?? []} - getOptionLabel={(option: any) => { - if (option) { - return option.title; - } else { - return ""; - } - }} - renderOption={(props, option: any) => ( - - )} - sx={{ width: "100%" }} - renderInput={(params: any) => } - /> - ); -}; diff --git a/apps/link/app/(main)/_components/SetupModeWarning.tsx b/apps/link/app/(main)/_components/SetupModeWarning.tsx deleted file mode 100644 index 0411916..0000000 --- a/apps/link/app/(main)/_components/SetupModeWarning.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { FC } from "react"; -import { Box } from "@mui/material"; - -interface SetupModeWarningProps { - setupModeActive: boolean; -} - -export const SetupModeWarning: FC = ({ - setupModeActive, -}) => - setupModeActive ? ( - - - Setup Mode Active - - - ) : null; diff --git a/apps/link/app/(main)/_components/Sidebar.tsx b/apps/link/app/(main)/_components/Sidebar.tsx deleted file mode 100644 index 4409398..0000000 --- a/apps/link/app/(main)/_components/Sidebar.tsx +++ /dev/null @@ -1,463 +0,0 @@ -"use client"; - -import { FC, useEffect, useState } from "react"; -import { - Box, - Grid, - Typography, - List, - ListItemButton, - ListItemIcon, - ListItemText, - ListItemSecondaryAction, - Drawer, - Collapse, -} from "@mui/material"; -import { - FeaturedPlayList as FeaturedPlayListIcon, - Person as PersonIcon, - Insights as InsightsIcon, - Logout as LogoutIcon, - Cottage as CottageIcon, - Settings as SettingsIcon, - ExpandCircleDown as ExpandCircleDownIcon, - Dvr as DvrIcon, - Assessment as AssessmentIcon, - LibraryBooks as LibraryBooksIcon, - School as SchoolIcon, -} from "@mui/icons-material"; -import { usePathname } from "next/navigation"; -import Link from "next/link"; -import Image from "next/image"; -import LinkLogo from "@app/../public/link-logo-small.png"; -import { useSession, signOut } from "next-auth/react"; -import { fonts } from "@link-stack/ui"; - -const openWidth = 270; -const closedWidth = 70; - -const MenuItem = ({ - name, - href, - Icon, - iconSize, - inset = false, - selected = false, - open = true, - badge, - depth = 0, - target = "_self", -}: any) => { - const { roboto } = fonts; - - return ( - - - {iconSize > 0 ? ( - - - - - - ) : ( - - - - {depth > 0 && ( - - )} - - )} - {open && ( - - {name} - - } - /> - )} - {open && badge && badge > 0 ? ( - - - {badge} - - - ) : null} - - - ); -}; - -interface SidebarProps { - open: boolean; - setOpen: (open: boolean) => void; -} - -export const Sidebar: FC = ({ - open, - setOpen, -}) => { - const pathname = usePathname(); - const { data: session } = useSession(); - const { poppins } = fonts; - const username = session?.user?.name || ""; - // @ts-ignore - const roles = session?.user?.roles || []; - - return ( - - { - setOpen!(!open); - }} - > - - - - - - - Link logo - - . - - {open && ( - - - CDR Link - - - )} - - - - - - - Hello - - - - - {open - ? username - : username - .split(" ") - .map((name) => name.substring(0, 1)) - .join("")} - - - - - - - - - - {roles.includes("admin") && ( - <> - - - - - - - - - - - - - )} - - - - - - ); -}; diff --git a/apps/link/app/(main)/_components/StyledDataGrid.tsx b/apps/link/app/(main)/_components/StyledDataGrid.tsx deleted file mode 100644 index a13a30d..0000000 --- a/apps/link/app/(main)/_components/StyledDataGrid.tsx +++ /dev/null @@ -1,95 +0,0 @@ -"use client"; - -import { FC } from "react"; -import { Box } from "@mui/material"; -import { - DataGridPro, - GridColDef, - GridColumnVisibilityModel, - GridRowSelectionModel, -} from "@mui/x-data-grid-pro"; -import { useCookies } from "react-cookie"; - -interface StyledDataGridProps { - name: string; - columns: GridColDef[]; - rows: any[]; - // eslint-disable-next-line no-unused-vars - onRowClick?: (row: any) => void; - height?: string; - selectedRows?: GridRowSelectionModel; - // eslint-disable-next-line no-unused-vars - setSelectedRows?: (rows: GridRowSelectionModel) => void; -} - -export const StyledDataGrid: FC = ({ - name, - columns, - rows, - onRowClick, - height = "100%", - selectedRows, - setSelectedRows, -}) => { - const cookieName = `${name}DataGridColumnState`; - const [cookies, setCookie] = useCookies([cookieName]); - const handleColumnVisibilityChange = (model: GridColumnVisibilityModel) => - setCookie(cookieName, model, { path: "/" }); - - return ( - - - - ); -}; diff --git a/apps/link/app/(main)/_components/ZammadWrapper.tsx b/apps/link/app/(main)/_components/ZammadWrapper.tsx deleted file mode 100644 index 4daec0f..0000000 --- a/apps/link/app/(main)/_components/ZammadWrapper.tsx +++ /dev/null @@ -1,154 +0,0 @@ -"use client"; - -import { FC, useState, useEffect, useRef } from "react"; -import { useRouter } from "next/navigation"; -import Iframe from "react-iframe"; -import { useSession } from "next-auth/react"; -import { Box, Grid, CircularProgress } from "@mui/material"; - -type ZammadWrapperProps = { - path: string; - hideSidebar?: boolean; -}; - -export const ZammadWrapper: FC = ({ - path, - hideSidebar = true, -}) => { - const router = useRouter(); - const { data: session } = useSession({ required: true }); - const timeoutRef = useRef(null); - const [hashCheckComplete, setHashCheckComplete] = useState(false); - const [authenticated, setAuthenticated] = useState(false); - const [display, setDisplay] = useState("none"); - const url = `/zammad${path}`; - const id = url.replace(/[^a-zA-Z0-9]/g, ""); - - useEffect(() => { - const hash = window?.location?.hash; - if (hash && hash.startsWith("#ticket/zoom/")) { - const ticketID = hash.split("/").pop(); - router.push(`/tickets/${ticketID}`); - } - setHashCheckComplete(true); - }); - - useEffect(() => { - if (!hashCheckComplete) return; - - const checkAuthenticated = async () => { - const res = await fetch("/zammad/auth/sso", { - method: "GET", - redirect: "manual", - }); - if (res.type === "opaqueredirect") { - setAuthenticated(true); - } else { - setAuthenticated(false); - } - }; - - checkAuthenticated(); - }, [path, hashCheckComplete]); - - useEffect(() => { - if (session === null) { - timeoutRef.current = setTimeout(() => { - if (session === null) { - router.push("/login"); - } - }, 3000); - } - - if (session !== null) { - clearTimeout(timeoutRef.current); - } - - return () => clearTimeout(timeoutRef.current); - }, [session]); - - if (!session || !authenticated) { - return ( - - - - - - - - ); - } - - if (session && authenticated) { - return ( - + + diff --git a/packages/zammad-addon-link/src/config/initializers/opensearch_compatibility.rb b/packages/zammad-addon-link/src/config/initializers/opensearch_compatibility.rb new file mode 100644 index 0000000..b77a3ac --- /dev/null +++ b/packages/zammad-addon-link/src/config/initializers/opensearch_compatibility.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# OpenSearch Compatibility Fix +# +# This initializer patches SearchIndexBackend to use 'flat_object' instead of 'flattened' +# for field type mapping. OpenSearch uses 'flat_object' while Elasticsearch uses 'flattened'. +# +# Without this fix, search index creation fails with: +# [o.o.c.m.MetadataCreateIndexService] failed on parsing mappings on index creation +# org.opensearch.index.mapper.MapperParsingException: Failed to parse mapping [_doc]: +# No handler for type [flattened] declared on field [preferences] +# +# See: https://github.com/zammad/zammad/blob/develop/lib/search_index_backend.rb + +module SearchIndexBackendOpenSearchPatch + # Override the _mapping_item_type_es method to use flat_object instead of flattened + def _mapping_item_type_es(item_type) + # Call the original method + result = super(item_type) + + # Replace 'flattened' with 'flat_object' for OpenSearch compatibility + if result == 'flattened' + return 'flat_object' + end + + result + end +end + +# Apply the patch after Rails has finished loading all classes +Rails.application.config.after_initialize do + SearchIndexBackend.singleton_class.prepend(SearchIndexBackendOpenSearchPatch) + Rails.logger.info 'OpenSearch compatibility patch applied successfully' +end diff --git a/packages/zammad-addon-link/src/config/routes/opensearch.rb b/packages/zammad-addon-link/src/config/routes/opensearch.rb index 1803927..b53e467 100644 --- a/packages/zammad-addon-link/src/config/routes/opensearch.rb +++ b/packages/zammad-addon-link/src/config/routes/opensearch.rb @@ -1,7 +1,10 @@ # frozen_string_literal: true -Zammad::Application.routes.draw do - scope Rails.configuration.api_path do - match '/opensearch', to: 'opensearch#index', via: :get - end +# Copyright (C) 2025 Center for Digital Resilience +# License: AGPL-3.0-or-later + +Rails.application.routes.draw do + # OpenSearch Dashboards integration + get '/opensearch', to: 'opensearch#index' + get '/opensearch/*path', to: 'opensearch#proxy' end diff --git a/packages/zammad-addon-link/src/db/addon/link/20250114000001_add_opensearch_navigation.rb b/packages/zammad-addon-link/src/db/addon/link/20250114000001_add_opensearch_navigation.rb new file mode 100644 index 0000000..08e57b3 --- /dev/null +++ b/packages/zammad-addon-link/src/db/addon/link/20250114000001_add_opensearch_navigation.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +# Copyright (C) 2025 Center for Digital Resilience +# License: AGPL-3.0-or-later + +class AddOpensearchNavigation < ActiveRecord::Migration[5.2] + def self.up + # Add permission for accessing OpenSearch dashboards + Permission.create_if_not_exists( + name: 'user_preferences.opensearch', + note: 'Access to OpenSearch Dashboards', + preferences: {} + ) + + # Create a navigation entry for OpenSearch + # This will add a menu item in the sidebar + NavBar.create_if_not_exists( + name: 'OpenSearch', + link: '/opensearch', + prio: 2600, # Position in menu (after Dashboard=1400, Tickets=2000, Stats=2500) + permission: ['user_preferences.opensearch'], + parent: '', + active: true + ) + + # Grant permission to admin and agent roles + %w[Admin Agent].each do |role_name| + role = Role.find_by(name: role_name) + next if !role + + role.permission_grant('user_preferences.opensearch') + end + + Rails.logger.info 'OpenSearch navigation menu item created successfully' + end + + def self.down + # Remove navigation entry + navbar = NavBar.find_by(name: 'OpenSearch') + navbar&.destroy + + # Remove permission + permission = Permission.find_by(name: 'user_preferences.opensearch') + permission&.destroy + + Rails.logger.info 'OpenSearch navigation menu item removed' + end +end diff --git a/packages/zammad-addon-link/src/public/assets/javascripts/qrcode.min.js b/packages/zammad-addon-link/src/public/assets/javascripts/qrcode.min.js new file mode 100644 index 0000000..56e154e --- /dev/null +++ b/packages/zammad-addon-link/src/public/assets/javascripts/qrcode.min.js @@ -0,0 +1,8 @@ +/*! + * QRCode.js v1.0.0 + * https://github.com/davidshimjs/qrcodejs + * + * Copyright (c) 2012 davidshimjs + * Licensed MIT + */ +var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j=0?p.get(q):0}}for(var r=0,m=0;mm;m++)for(var j=0;jm;m++)for(var j=0;j=0;)b^=f.G15<=0;)b^=f.G18<>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;cf;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorLight,width:"100%",height:"100%"})),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(j),y:String(i)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=[''],h=0;d>h;h++){g.push("");for(var i=0;d>i;i++)g.push('');g.push("")}g.push("
"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); From e9afa065b5ae7d77c77368d2cddb6cc7a4ccced1 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Thu, 12 Feb 2026 20:52:47 +0100 Subject: [PATCH 28/38] Fix missing signal notifications field --- .../views/PersonalSettingNotifications.vue | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue b/packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue index d8a06c0..5b186b5 100644 --- a/packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue +++ b/packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue @@ -61,15 +61,19 @@ const soundOptions = Object.keys(EnumNotificationSoundFile).map((sound) => ({ value: sound, })) -// CDR Link: Check if any Signal notification checkbox is selected in the matrix -const hasSignalNotificationSelected = computed(() => { - const matrix = values.value?.matrix - if (!matrix) return false +// CDR Link: Track if any Signal notification checkbox is selected +// Using a ref + onChangedField for reactivity instead of computed on values +const showSignalPhoneField = ref(false) - // Check all rows (create, update, reminderReached, escalation) for signal channel enabled +// Helper to check if any signal checkbox is enabled in matrix +const checkSignalSelected = (matrix: any): boolean => { + if (!matrix) return false const rows = ['create', 'update', 'reminderReached', 'escalation'] return rows.some((row) => matrix[row]?.channel?.signal === true) -}) +} + +// CDR Link: Key for form re-rendering when signal field visibility changes +const formKey = computed(() => `notifications-${showSignalPhoneField.value}`) // CDR Link: Dynamically build schema based on signal notification setting const schema = computed(() => { @@ -95,7 +99,7 @@ const schema = computed(() => { // CDR Link: Add Signal phone number field only when Signal notifications are enabled // AND at least one Signal notification checkbox is selected - if (signalNotificationEnabled.value && hasSignalNotificationSelected.value) { + if (signalNotificationEnabled.value && showSignalPhoneField.value) { baseSchema.push({ type: 'text', name: 'signal_uid', @@ -155,12 +159,25 @@ watch(initialFormValues, (newValues) => { if (isEqual(values.value, newValues) && !isDirty.value) return formReset({ values: newValues }) -}) + // CDR Link: Update signal field visibility from initial values + showSignalPhoneField.value = checkSignalSelected(newValues.matrix) +}, { immediate: true }) onChangedField('file', (fileName) => { new Audio(`/assets/sounds/${fileName?.toString()}.mp3`)?.play() }) +// CDR Link: Watch matrix field changes to show/hide signal phone field +onChangedField('matrix', (matrix) => { + showSignalPhoneField.value = checkSignalSelected(matrix) +}) + +// CDR Link: Get CSRF token from meta tag +const getCsrfToken = (): string => { + const metaTag = document.querySelector('meta[name="csrf-token"]') + return metaTag?.getAttribute('content') || '' +} + // CDR Link: Save signal_uid via REST API const saveSignalUid = async (signalUid: string | undefined) => { if (!signalNotificationEnabled.value) return @@ -170,6 +187,7 @@ const saveSignalUid = async (signalUid: string | undefined) => { method: 'PUT', headers: { 'Content-Type': 'application/json', + 'X-CSRF-Token': getCsrfToken(), }, body: JSON.stringify({ notification_config: { @@ -287,7 +305,8 @@ const onResetToDefaultSettings = async () => {
Date: Fri, 13 Feb 2026 11:14:04 +0100 Subject: [PATCH 29/38] Add support for signal usernames --- .../app/views/profile/notification.jst.eco | 6 +-- .../views/PersonalSettingNotifications.vue | 8 ++-- .../app/jobs/create_ticket_from_form_job.rb | 45 +++++++++++++++---- .../20260212000001_add_signal_username.rb | 44 ++++++++++++++++++ .../zammad-addon-link/src/lib/cdr_signal.rb | 2 +- 5 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 packages/zammad-addon-link/src/db/addon/link/20260212000001_add_signal_username.rb diff --git a/packages/zammad-addon-link/src/app/assets/javascripts/app/views/profile/notification.jst.eco b/packages/zammad-addon-link/src/app/assets/javascripts/app/views/profile/notification.jst.eco index 65e43f9..23a563b 100644 --- a/packages/zammad-addon-link/src/app/assets/javascripts/app/views/profile/notification.jst.eco +++ b/packages/zammad-addon-link/src/app/assets/javascripts/app/views/profile/notification.jst.eco @@ -10,10 +10,10 @@ <% if @signal_notification_enabled: %>
-

<%- @T('Signal Phone Number') %>

+

<%- @T('Signal Recipient') %>

- -

<%- @T('Use international format with country code (e.g., +1234567890)') %>

+ +

<%- @T('Phone number (+1234567890) or username with u: prefix (u:john.42)') %>

<% end %> diff --git a/packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue b/packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue index 5b186b5..c7cd4f2 100644 --- a/packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue +++ b/packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue @@ -97,16 +97,16 @@ const schema = computed(() => { }, ] - // CDR Link: Add Signal phone number field only when Signal notifications are enabled + // CDR Link: Add Signal recipient field only when Signal notifications are enabled // AND at least one Signal notification checkbox is selected if (signalNotificationEnabled.value && showSignalPhoneField.value) { baseSchema.push({ type: 'text', name: 'signal_uid', - label: __('Signal Phone Number'), - help: __('Use international format with country code (e.g., +1234567890). Required when Signal notifications are enabled in the matrix.'), + label: __('Signal Recipient'), + help: __('Phone number (+1234567890) or username with u: prefix (u:john.42)'), props: { - placeholder: '+1234567890', + placeholder: '+1234567890 or u:username.42', }, } as any) } diff --git a/packages/zammad-addon-link/src/app/jobs/create_ticket_from_form_job.rb b/packages/zammad-addon-link/src/app/jobs/create_ticket_from_form_job.rb index ad4c929..685bcd0 100644 --- a/packages/zammad-addon-link/src/app/jobs/create_ticket_from_form_job.rb +++ b/packages/zammad-addon-link/src/app/jobs/create_ticket_from_form_job.rb @@ -32,6 +32,7 @@ class CreateTicketFromFormJob < ApplicationJob email = get_field_value(form_data, 'email', mapping) raw_phone = get_field_value(form_data, 'phone', mapping) raw_signal_account = get_field_value(form_data, 'signalAccount', mapping) + raw_signal_username = get_field_value(form_data, 'signalUsername', mapping) organization = get_field_value(form_data, 'organization', mapping) type_of_support = get_field_value(form_data, 'typeOfSupport', mapping) description_of_issue = get_field_value(form_data, 'descriptionOfIssue', mapping) @@ -39,10 +40,11 @@ class CreateTicketFromFormJob < ApplicationJob # Sanitize phone numbers phone = sanitize_phone_number(raw_phone) signal_account = sanitize_phone_number(raw_signal_account) + signal_username = normalize_signal_username(raw_signal_username) # Validate contact info - unless email.present? || phone.present? || signal_account.present? - raise 'At least one contact method (email, phone, or signalAccount) is required' + unless email.present? || phone.present? || signal_account.present? || signal_username.present? + raise 'At least one contact method (email, phone, signalAccount, or signalUsername) is required' end # Build ticket title @@ -60,7 +62,8 @@ class CreateTicketFromFormJob < ApplicationJob phone: phone, email: email, first_name: first_name, - last_name: last_name + last_name: last_name, + signal_username: signal_username ) Rails.logger.info "Formstack: Using customer #{customer.id} for ticket" @@ -75,18 +78,20 @@ class CreateTicketFromFormJob < ApplicationJob article_type = Ticket::Article::Type.find_by(name: article_type_name) # Check for Signal integration + # Use phone number if available, otherwise fall back to username + signal_recipient = signal_account.presence || signal_username signal_article_type = nil signal_channel_id = nil signal_bot_token = nil - if signal_account.present? + if signal_recipient.present? signal_channel = Channel.where(area: 'Signal::Number', active: true).first if signal_channel signal_channel_id = signal_channel.id signal_bot_token = signal_channel.options[:bot_token] signal_article_type = Ticket::Article::Type.find_by(name: 'cdr_signal') - Rails.logger.info "Formstack: Found Signal channel #{signal_channel_id} for Signal ticket" + Rails.logger.info "Formstack: Found Signal channel #{signal_channel_id} for Signal ticket (recipient: #{signal_recipient})" end end @@ -102,15 +107,15 @@ class CreateTicketFromFormJob < ApplicationJob ticket_data.merge!(zammad_fields) # Add Signal preferences if applicable - if signal_channel_id && signal_bot_token && signal_article_type && signal_account + if signal_channel_id && signal_bot_token && signal_article_type && signal_recipient ticket_data[:preferences] = { channel_id: signal_channel_id, cdr_signal: { bot_token: signal_bot_token, - chat_id: signal_account + chat_id: signal_recipient } } - Rails.logger.info "Formstack: Adding Signal preferences to ticket" + Rails.logger.info "Formstack: Adding Signal preferences to ticket (chat_id: #{signal_recipient})" end # Create ticket @@ -267,7 +272,7 @@ class CreateTicketFromFormJob < ApplicationJob nil end - def find_or_create_customer(phone:, email:, first_name:, last_name:) + def find_or_create_customer(phone:, email:, first_name:, last_name:, signal_username: nil) customer = nil # Try phone first @@ -284,6 +289,11 @@ class CreateTicketFromFormJob < ApplicationJob end end + # Try Signal username + if customer.nil? && signal_username.present? + customer = User.find_by(signal_username: signal_username) + end + # Create new customer if not found unless customer user_data = { @@ -296,14 +306,31 @@ class CreateTicketFromFormJob < ApplicationJob } user_data[:email] = email if email.present? user_data[:phone] = phone if phone.present? + user_data[:signal_username] = signal_username if signal_username.present? customer = User.create!(user_data) Rails.logger.info "Formstack: Created new customer #{customer.id}" end + # Update existing customer if they don't have username + if customer && signal_username.present? && customer.signal_username.blank? + customer.update!(signal_username: signal_username) + Rails.logger.info "Formstack: Updated customer #{customer.id} with signal_username" + end + customer end + def normalize_signal_username(raw_username) + return nil unless raw_username.present? + + username = raw_username.to_s.strip + return nil if username.empty? + + # Add u: prefix if not present + username.start_with?('u:') ? username : "u:#{username}" + end + def get_zammad_field_values(form_data, mapping) result = {} zammad_fields = mapping['zammadFields'] || {} diff --git a/packages/zammad-addon-link/src/db/addon/link/20260212000001_add_signal_username.rb b/packages/zammad-addon-link/src/db/addon/link/20260212000001_add_signal_username.rb new file mode 100644 index 0000000..4f3dd29 --- /dev/null +++ b/packages/zammad-addon-link/src/db/addon/link/20260212000001_add_signal_username.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +class AddSignalUsername < ActiveRecord::Migration[5.2] + def self.up + add_column :users, :signal_username, :string, limit: 50 + add_index :users, :signal_username + User.reset_column_information + + ObjectManager::Attribute.add( + force: true, + object: 'User', + name: 'signal_username', + display: 'Signal Username', + data_type: 'input', + data_option: { + type: 'text', + maxlength: 50, + null: true, + item_class: 'formGroup--halfSize', + }, + editable: false, + active: true, + screens: { + signup: {}, + invite_agent: {}, + invite_customer: {}, + edit: { '-all-' => { null: true } }, + create: { '-all-' => { null: true } }, + view: { '-all-' => { shown: true } } + }, + to_create: false, + to_migrate: false, + to_delete: false, + position: 721, + created_by_id: 1, + updated_by_id: 1 + ) + end + + def self.down + ObjectManager::Attribute.find_by(name: 'signal_username', object: ObjectLookup.find_by(name: 'User'))&.destroy + remove_column :users, :signal_username + end +end diff --git a/packages/zammad-addon-link/src/lib/cdr_signal.rb b/packages/zammad-addon-link/src/lib/cdr_signal.rb index d7e4d29..7f2cef4 100644 --- a/packages/zammad-addon-link/src/lib/cdr_signal.rb +++ b/packages/zammad-addon-link/src/lib/cdr_signal.rb @@ -333,7 +333,7 @@ class CdrSignal # Use Signal CLI API api = CdrSignalApi.new - # Check if we need to create a group (auto-groups enabled, recipient is a phone number) + # Check if we need to create a group (auto-groups enabled, recipient is not already a group) is_group_id = recipient.start_with?('group.') final_recipient = recipient From 99b92fe4ce06fed16af06be04dd98903d0312cd7 Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Fri, 13 Feb 2026 18:34:13 +0100 Subject: [PATCH 30/38] Add Claude .md and skill --- .claude/skills/zammad-compat/SKILL.md | 197 ++++++++++++++++++++++++++ .gitignore | 8 ++ CLAUDE.md | 114 +++++++++++++++ 3 files changed, 319 insertions(+) create mode 100644 .claude/skills/zammad-compat/SKILL.md create mode 100644 CLAUDE.md diff --git a/.claude/skills/zammad-compat/SKILL.md b/.claude/skills/zammad-compat/SKILL.md new file mode 100644 index 0000000..3c267c4 --- /dev/null +++ b/.claude/skills/zammad-compat/SKILL.md @@ -0,0 +1,197 @@ +--- +name: zammad-compat +description: Check upstream Zammad for breaking changes before upgrading the addon +disable-model-invocation: true +argument-hint: "[target-version]" +allowed-tools: Bash(git clone *), Bash(git -C /tmp/zammad-upstream *) +--- + +# Zammad Upstream Compatibility Check + +Check the upstream zammad/zammad repository for changes that could break or require updates to our Zammad addon (`packages/zammad-addon-link`). + +## Arguments + +- `$ARGUMENTS` - Optional: target Zammad version/tag/branch to compare against (e.g. `6.6.0`, `stable`). If not provided, ask the user what version to compare against. The current version is in `docker/zammad/Dockerfile` as the `ZAMMAD_VERSION` ARG. + +## Setup + +1. Read the current Zammad version from `docker/zammad/Dockerfile` (the `ARG ZAMMAD_VERSION=` line). +2. Clone or update the upstream Zammad repository: + - If `/tmp/zammad-upstream` does not exist, clone it: `git clone --bare https://github.com/zammad/zammad.git /tmp/zammad-upstream` + - If it exists, update it: `git -C /tmp/zammad-upstream fetch --all --tags` +3. Determine the version range. The current version is the `ZAMMAD_VERSION` from step 1. The target version is the argument or user-provided version. Both versions should be used as git refs (tags are typically in the format `X.Y.Z`). + +## Checks to Perform + +Run ALL of these checks and compile results into a single report. + +### 1. Replaced Stock Files + +These are stock Zammad files that our addon REPLACES with modified copies. Changes upstream mean we need to port those changes into our modified versions. + +For each file below, diff the upstream version between the current and target version. Report any changes found. + +**Vue/TypeScript (Desktop UI):** +- `app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/ArticleReply.vue` +- `app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue` +- `app/frontend/apps/desktop/components/Form/fields/FieldNotifications/FieldNotificationsInput.vue` +- `app/frontend/apps/desktop/components/Form/fields/FieldNotifications/types.ts` + +**CoffeeScript (Legacy UI):** +- `app/assets/javascripts/app/controllers/_profile/notification.coffee` +- `app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee` +- `app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee` +- `app/assets/javascripts/app/views/generic/notification_matrix.jst.eco` +- `app/assets/javascripts/app/views/profile/notification.jst.eco` + +Command pattern for each file: +```bash +git -C /tmp/zammad-upstream diff -- +``` + +If a file does not exist at either version, note that (it may have been added, removed, or renamed). + +### 2. Monkey-Patched Files + +These are files our addon patches at runtime via Ruby `prepend`, `include`, or `after_initialize` hooks. Changes to these files could break our patches. + +**Search Backend (OpenSearch compatibility patch):** +- `lib/search_index_backend.rb` - We prepend `SearchIndexBackendOpenSearchPatch` to override `_mapping_item_type_es`. Check if this method signature or the `'flattened'` string usage has changed. + +**Core Models (callback injection targets):** +- `app/models/ticket/article.rb` - We inject `after_create` callbacks via `include` for Signal and WhatsApp message delivery. Check for changes to the callback chain, model structure, or the `Sender`/`Type` lookup patterns. +- `app/models/link.rb` - We inject an `after_create` callback for Signal group setup on ticket split. Check for structural changes. + +**Transaction System:** +- `app/models/transaction/` directory - We register `Transaction::SignalNotification` as backend `0105_signal_notification`. Check if the transaction backend system has been refactored. + +**Icons:** +- `public/assets/images/icons.svg` - Our initializers append SVG icons at boot time. Check if the SVG structure or the icon injection mechanism has changed. + +Command pattern: +```bash +git -C /tmp/zammad-upstream diff -- +``` + +For the search backend specifically, also check if `_mapping_item_type_es` still exists and still returns `'flattened'`: +```bash +git -C /tmp/zammad-upstream show :lib/search_index_backend.rb | grep -n -A5 '_mapping_item_type_es\|flattened' +``` + +### 3. API Surface Dependencies + +These are Zammad APIs/interfaces/mixins our addon relies on. Changes could cause runtime failures. + +**Channel Driver Interface:** +- `app/models/channel/driver/` - Check if the driver base class or interface expectations have changed (methods: `fetchable?`, `disconnect`, `deliver`, `streamable?`). + +**Controller Concerns:** +- `app/controllers/concerns/creates_ticket_articles.rb` - Used by our webhook controllers. Check for interface changes. + +**Ticket Article Types & Senders:** +- `app/models/ticket/article/type.rb` and `app/models/ticket/article/sender.rb` - We look up types by name (`'signal message'`, `'whatsapp message'`). Check for changes in how types are registered or looked up. + +**Authentication/Authorization:** +- `app/policies/` directory structure - We create policies matching `controllers/` names. Check if the policy naming convention or base class has changed. + +**Package System:** +- `lib/package.rb` or the package install/uninstall API - We use `Package.install(file:)` and `Package.uninstall(name:, version:)` in setup.rb. + +**Scheduler/Job System:** +- `app/jobs/` base class patterns - Our jobs inherit from ApplicationJob. Check for changes. + +Command pattern: +```bash +git -C /tmp/zammad-upstream diff --stat -- +git -C /tmp/zammad-upstream diff -- +``` + +### 4. Path Collision Detection + +Check if the target Zammad version has added any NEW files at paths that collide with our addon files. Our addon installs files at these paths: + +**Controllers:** `app/controllers/channels_cdr_signal_controller.rb`, `channels_cdr_voice_controller.rb`, `channels_cdr_whatsapp_controller.rb`, `cdr_signal_channels_controller.rb`, `cdr_ticket_article_types_controller.rb`, `formstack_controller.rb`, `opensearch_controller.rb` + +**Models:** `app/models/channel/driver/cdr_signal.rb`, `cdr_whatsapp.rb`, `app/models/ticket/article/enqueue_communicate_cdr_signal_job.rb`, `enqueue_communicate_cdr_whatsapp_job.rb`, `app/models/link/setup_split_signal_group.rb`, `app/models/transaction/signal_notification.rb` + +**Jobs:** `app/jobs/communicate_cdr_signal_job.rb`, `communicate_cdr_whatsapp_job.rb`, `signal_notification_job.rb`, `create_ticket_from_form_job.rb` + +**Libraries:** `lib/cdr_signal.rb`, `cdr_signal_api.rb`, `cdr_signal_poller.rb`, `cdr_whatsapp.rb`, `cdr_whatsapp_api.rb`, `signal_notification_sender.rb` + +**Routes:** `config/routes/cdr_signal_channels.rb`, `channel_cdr_signal.rb`, `channel_cdr_voice.rb`, `channel_cdr_whatsapp.rb`, `cdr_ticket_article_types.rb`, `formstack.rb`, `opensearch.rb` + +**Frontend Plugins:** `app/frontend/shared/entities/ticket-article/action/plugins/cdr_signal.ts`, `cdr_whatsapp.ts`, `app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/article-type/plugins/signalMessage.ts`, `whatsappMessage.ts` + +Check if any of these paths exist in the target version: +```bash +for path in ; do + git -C /tmp/zammad-upstream show :$path 2>/dev/null && echo "COLLISION: $path exists upstream" +done +``` + +### 5. Dockerfile Patch Targets + +Check files that are patched at Docker build time via `sed`: + +- `lib/search_index_backend.rb` - `sed` replaces `'flattened'` with `'flat_object'`. Verify the string still exists in the target version. +- `contrib/nginx/zammad.conf` - Structure modified for embedded mode. Check for format changes. +- `docker-entrypoint.sh` - We inject addon install commands after the `# es config` comment. Verify this comment/anchor still exists. + +Check the upstream Docker entrypoint: +```bash +git -C /tmp/zammad-upstream show :contrib/docker/docker-entrypoint.sh 2>/dev/null | grep -n 'es config' || echo "Anchor comment not found - check entrypoint structure" +``` + +Also check the Zammad Docker Compose repo if relevant (the base image may come from `zammad/zammad-docker-compose`). + +### 6. Database Schema Conflicts + +Check if the target Zammad version adds any columns or tables that could conflict with our migrations: +- Column names: `whatsapp_uid`, `signal_uid`, `signal_username` on the users table +- Setting names containing: `signal_notification`, `cdr_link`, `formstack`, `opensearch_dashboard` + +```bash +git -C /tmp/zammad-upstream diff -- db/migrate/ | grep -i 'signal\|whatsapp\|formstack\|opensearch' +``` + +### 7. Frontend Build System + +Check if the Vite/asset pipeline configuration has changed significantly, since our addon relies on being compiled into the Zammad frontend: + +```bash +git -C /tmp/zammad-upstream diff --stat -- vite.config.ts app/frontend/vite.config.ts config/initializers/assets.rb Gemfile +``` + +Also check if CoffeeScript/Sprockets support has been removed (would break our legacy UI files): +```bash +git -C /tmp/zammad-upstream show :Gemfile 2>/dev/null | grep -i 'coffee\|sprockets' +``` + +## Report Format + +Compile all findings into a structured report: + +``` +## Zammad Compatibility Report: -> + +### CRITICAL (Action Required Before Upgrade) +- [List files that changed upstream AND are replaced by our addon - these need manual merging] +- [List any broken monkey-patch targets] +- [List any path collisions] + +### WARNING (Review Needed) +- [List API surface changes that could affect our code] +- [List Dockerfile patch targets that changed] +- [List build system changes] + +### INFO (No Action Needed) +- [List files checked with no changes] +- [List confirmed-safe paths] + +### Recommended Actions +- For each CRITICAL item, describe what needs to be done +- Note any files that should be re-copied from upstream and re-patched +``` + +For each changed file in CRITICAL, show the upstream diff so the user can see what changed and decide how to integrate it. diff --git a/.gitignore b/.gitignore index 2bea406..44a541f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,11 @@ ENVIRONMENT_VARIABLES_MIGRATION.md local-scripts/* docs/ packages/zammad-addon-link/test/ + +# Allow Claude Code project config (overrides global gitignore) +!CLAUDE.md +!.claude/ +.claude/** +!.claude/skills/ +!.claude/skills/** +.claude/settings.local.json diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..a29fba6 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,114 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Repository Overview + +This is a monorepo for CDR Link - a Zammad addon and supporting services built by the Center for Digital Resilience. It adds Signal, WhatsApp, and voice channel support to Zammad via a custom `.zpm` addon package, along with a standalone WhatsApp bridge service. It uses pnpm workspaces and Turborepo for orchestration. + +**Tech Stack:** +- Zammad 6.5.x as the core helpdesk platform +- Ruby (Rails initializers, controllers, models, jobs) for the Zammad addon +- TypeScript/Node.js for build tooling and the WhatsApp bridge +- CoffeeScript for Zammad legacy UI extensions +- Vue 3 for Zammad desktop UI extensions +- Docker for containerization +- PostgreSQL, Redis, Memcached as backing services + +## Project Structure + +``` +apps/ + bridge-whatsapp/ # Standalone WhatsApp bridge (Hapi.js + Baileys) +packages/ + zammad-addon-link/ # Zammad addon source (Ruby, CoffeeScript, Vue, TS) + src/ # Addon source files (installed into /opt/zammad/) + scripts/build.ts # Builds .zpm package from src/ + scripts/migrate.ts # Generates new migration stubs +docker/ + zammad/ # Custom Zammad Docker image + Dockerfile # Extends zammad/zammad-docker-compose base image + install.rb # Extracts addon files from .zpm at build time + setup.rb # Registers addon packages at container startup + addons/ # Built .zpm files (gitignored, generated by turbo build) + compose/ # Docker Compose service definitions +``` + +## Common Development Commands + +```bash +pnpm install # Install all dependencies +turbo build # Build all packages (generates .zpm files) +npm run docker:zammad:build # Build custom Zammad Docker image +npm run docker:all:up # Start all Docker services +npm run docker:all:down # Stop all Docker services +npm run docker:zammad:restart # Restart railsserver + scheduler (after Ruby changes) +npm run update-version # Update version across all packages +npm run clean # Remove all build artifacts and dependencies +``` + +## Zammad Addon Architecture + +### Addon Build & Deploy Pipeline + +1. `turbo build` runs `tsx scripts/build.ts` in `packages/zammad-addon-link/` +2. Build script base64-encodes all files under `src/`, produces `docker/zammad/addons/zammad-addon-link-v{version}.zpm` +3. `docker/zammad/Dockerfile` builds a custom image: + - Copies `.zpm` files and runs `install.rb` to extract addon files into the Zammad directory tree + - Rebuilds Vite frontend (`bundle exec vite build`) to include addon Vue components + - Precompiles assets (`rake assets:precompile`) to include addon CoffeeScript + - Applies `sed` patches (OpenSearch compatibility, entrypoint injection) +4. At container startup, `setup.rb` registers the addon via `Package.install()` and runs migrations + +### How the Addon Extends Zammad + +**New files (no upstream conflict risk):** Controllers, channel drivers, jobs, routes, policies, library classes, views, CSS, SVG icons, frontend plugins. These add Signal/WhatsApp/voice channel support. + +**Replaced stock files (HIGH conflict risk - must be manually merged on Zammad upgrades):** +- `app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/ArticleReply.vue` - Adds channel whitelist filtering via `cdr_link_allowed_channels` setting +- `app/frontend/apps/desktop/pages/personal-setting/views/PersonalSettingNotifications.vue` - Adds Signal notification recipient field +- `app/frontend/apps/desktop/components/Form/fields/FieldNotifications/FieldNotificationsInput.vue` - Adds Signal column to notification matrix +- `app/frontend/apps/desktop/components/Form/fields/FieldNotifications/types.ts` - Extended notification types +- `app/assets/javascripts/app/controllers/_profile/notification.coffee` - Signal notification prefs (legacy UI) +- `app/assets/javascripts/app/controllers/_ui_element/notification_matrix.coffee` - Signal column (legacy UI) +- `app/assets/javascripts/app/lib/mixins/ticket_notification_matrix.coffee` - Notification matrix mixin +- `app/assets/javascripts/app/views/generic/notification_matrix.jst.eco` - Notification matrix template +- `app/assets/javascripts/app/views/profile/notification.jst.eco` - Notification profile template + +**Runtime monkey-patches (HIGH conflict risk):** +- `config/initializers/opensearch_compatibility.rb` - Prepends to `SearchIndexBackend._mapping_item_type_es()` to replace `'flattened'` with `'flat_object'` for OpenSearch +- `config/initializers/cdr_signal.rb` - Injects `after_create` callbacks into `Ticket::Article` and `Link` models +- `config/initializers/cdr_whatsapp.rb` - Injects `after_create` callback into `Ticket::Article` + +**Dockerfile-level patches:** +- `lib/search_index_backend.rb` - `sed` replaces `'flattened'` with `'flat_object'` +- `/docker-entrypoint.sh` - `sed` injects addon install commands after `# es config` anchor +- `contrib/nginx/zammad.conf` - Adds `/link` proxy location in embedded mode + +### Key Zammad API Dependencies + +The addon depends on these Zammad interfaces remaining stable: +- `Channel::Driver` interface (`fetchable?`, `disconnect`, `deliver`, `streamable?`) +- `Ticket::Article` model callbacks and `Sender`/`Type` lookup by name +- `Link` model and `Link::Type`/`Link::Object` +- `SearchIndexBackend._mapping_item_type_es` method +- `Transaction` backend registration system +- `Package.install(file:)` / `Package.uninstall(name:, version:)` API +- `CreatesTicketArticles` controller concern +- Policy naming convention (`controllers/_controller_policy.rb`) + +## Zammad Development Notes + +- After changing any Ruby files, restart railsserver and scheduler: `npm run docker:zammad:restart` +- The addon must be rebuilt (`turbo build`) and the Docker image rebuilt (`npm run docker:zammad:build`) for changes to take effect in Docker +- Use `/zammad-compat ` to check upstream Zammad for breaking changes before upgrading +- The current Zammad base version is set in `docker/zammad/Dockerfile` as `ARG ZAMMAD_VERSION` + +## Docker Services + +Defined in `docker/compose/`: +- **zammad.yml**: zammad-init, zammad-railsserver, zammad-nginx, zammad-scheduler, zammad-websocket, zammad-memcached, zammad-redis +- **bridge-whatsapp.yml**: bridge-whatsapp +- **postgresql.yml**: postgresql +- **signal-cli-rest-api.yml**: signal-cli-rest-api +- **opensearch.yml**: opensearch + dashboards From 40c14ece946240ea1768f321904440b7be01089f Mon Sep 17 00:00:00 2001 From: Darren Clarke Date: Fri, 13 Feb 2026 21:04:36 +0100 Subject: [PATCH 31/38] Latest zammad compatibility --- .claude/skills/zammad-compat/SKILL.md | 2 +- .dockerignore | 16 +- docker/compose/zammad.yml | 15 +- docker/zammad/Dockerfile | 197 +++++++++++------- .../controllers/_profile/notification.coffee | 2 +- .../FieldNotificationsInput.vue | 2 +- .../Form/fields/FieldNotifications/types.ts | 2 +- .../views/PersonalSettingNotifications.vue | 10 +- .../TicketDetailView/ArticleReply.vue | 2 +- ...atsappMessage.ts => cdrWhatsappMessage.ts} | 0 .../app/models/channel/driver/cdr_signal.rb | 4 - .../app/models/channel/driver/cdr_whatsapp.rb | 4 - ...0250114000001_add_opensearch_navigation.rb | 22 +- 13 files changed, 157 insertions(+), 121 deletions(-) rename packages/zammad-addon-link/src/app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/article-type/plugins/{whatsappMessage.ts => cdrWhatsappMessage.ts} (100%) diff --git a/.claude/skills/zammad-compat/SKILL.md b/.claude/skills/zammad-compat/SKILL.md index 3c267c4..bfde60d 100644 --- a/.claude/skills/zammad-compat/SKILL.md +++ b/.claude/skills/zammad-compat/SKILL.md @@ -121,7 +121,7 @@ Check if the target Zammad version has added any NEW files at paths that collide **Routes:** `config/routes/cdr_signal_channels.rb`, `channel_cdr_signal.rb`, `channel_cdr_voice.rb`, `channel_cdr_whatsapp.rb`, `cdr_ticket_article_types.rb`, `formstack.rb`, `opensearch.rb` -**Frontend Plugins:** `app/frontend/shared/entities/ticket-article/action/plugins/cdr_signal.ts`, `cdr_whatsapp.ts`, `app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/article-type/plugins/signalMessage.ts`, `whatsappMessage.ts` +**Frontend Plugins:** `app/frontend/shared/entities/ticket-article/action/plugins/cdr_signal.ts`, `cdr_whatsapp.ts`, `app/frontend/apps/desktop/pages/ticket/components/TicketDetailView/article-type/plugins/signalMessage.ts`, `cdrWhatsappMessage.ts` Check if any of these paths exist in the target version: ```bash diff --git a/.dockerignore b/.dockerignore index 923dc15..95f0c27 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,4 +2,18 @@ node_modules out signald docker-compose.yml -README.md \ No newline at end of file +README.md +.git +.aidocs/zammad/.git +.aidocs/zammad/node_modules +.aidocs/zammad/spec +.aidocs/zammad/test +.aidocs/zammad/.github +.aidocs/zammad/.gitlab +.aidocs/zammad/.dev +.aidocs/zammad/.devcontainer +apps/ +packages/ +.turbo +*.tsbuildinfo +coverage diff --git a/docker/compose/zammad.yml b/docker/compose/zammad.yml index 1ec1dba..5c27b78 100644 --- a/docker/compose/zammad.yml +++ b/docker/compose/zammad.yml @@ -34,7 +34,8 @@ services: POSTGRESQL_USER: zammad POSTGRESQL_PASS: ${ZAMMAD_DATABASE_PASSWORD} build: - context: ../zammad + context: ../../ + dockerfile: docker/zammad/Dockerfile args: <<: *common-zammad-args image: registry.gitlab.com/digiresilience/link/link-stack/zammad:${LINK_STACK_VERSION} @@ -63,7 +64,8 @@ services: depends_on: - zammad-railsserver build: - context: ../zammad + context: ../../ + dockerfile: docker/zammad/Dockerfile args: <<: *common-zammad-args image: registry.gitlab.com/digiresilience/link/link-stack/zammad:${LINK_STACK_VERSION} @@ -87,7 +89,8 @@ services: environment: <<: [*common-global-variables, *common-zammad-variables] build: - context: ../zammad + context: ../../ + dockerfile: docker/zammad/Dockerfile args: <<: *common-zammad-args image: registry.gitlab.com/digiresilience/link/link-stack/zammad:${LINK_STACK_VERSION} @@ -116,7 +119,8 @@ services: environment: <<: [*common-global-variables, *common-zammad-variables] build: - context: ../zammad + context: ../../ + dockerfile: docker/zammad/Dockerfile args: <<: *common-zammad-args image: registry.gitlab.com/digiresilience/link/link-stack/zammad:${LINK_STACK_VERSION} @@ -135,7 +139,8 @@ services: environment: <<: [*common-global-variables, *common-zammad-variables] build: - context: ../zammad + context: ../../ + dockerfile: docker/zammad/Dockerfile args: <<: *common-zammad-args image: registry.gitlab.com/digiresilience/link/link-stack/zammad:${LINK_STACK_VERSION} diff --git a/docker/zammad/Dockerfile b/docker/zammad/Dockerfile index 494d5b0..ef617b9 100644 --- a/docker/zammad/Dockerfile +++ b/docker/zammad/Dockerfile @@ -1,103 +1,140 @@ -ARG ZAMMAD_VERSION=6.5.2 +# Build Zammad with CDR Link addon +# Based on Zammad's upstream Dockerfile with addon injection steps. +# Zammad source is expected at .aidocs/zammad/ relative to the repo root. -FROM node:22-slim AS node +ARG RUBY_VERSION=3.4.8 +ARG NODE_VERSION=22 -FROM zammad/zammad-docker-compose:${ZAMMAD_VERSION} AS builder -USER root +# --- Base stage: runtime dependencies --- +FROM docker.io/library/ruby:$RUBY_VERSION-slim-trixie AS base -# Copy Node.js from node image -COPY --from=node /opt /opt +WORKDIR /opt/zammad + +ENV RAILS_ENV="production" \ + BUNDLE_DEPLOYMENT="1" \ + BUNDLE_PATH="/usr/local/bundle" \ + BUNDLE_WITHOUT="test development" \ + RAILS_LOG_TO_STDOUT="true" + +RUN apt-get update -qq && \ + apt-get install -y postgresql-common && \ + /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y && \ + apt-get install --no-install-recommends -y curl libimlib2 libpq5 nginx gnupg postgresql-client-17 && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + +# --- Node binary --- +FROM node:${NODE_VERSION}-trixie-slim AS node +RUN npm -g install corepack && corepack enable pnpm && \ + rm /usr/local/bin/yarn /usr/local/bin/yarnpkg + +# --- Build stage --- +FROM base AS build + +SHELL ["/bin/bash", "-o", "errexit", "-o", "pipefail", "-c"] + +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y build-essential git libimlib2-dev libpq-dev libyaml-dev && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + +# Install Ruby gems +COPY .aidocs/zammad/Gemfile .aidocs/zammad/Gemfile.lock ./ +COPY .aidocs/zammad/vendor/ vendor/ +RUN bundle install && \ + rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git + +# Install Node.js +COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules COPY --from=node /usr/local/bin /usr/local/bin -COPY --from=node /usr/local/lib /usr/local/lib -COPY --from=node /usr/lib /usr/lib -SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"] - -# Install pnpm for package management -RUN npm install -g pnpm -RUN pnpm --version - -ENV ZAMMAD_DIR=/opt/zammad -WORKDIR ${ZAMMAD_DIR} - -# Copy addons and installation scripts -RUN mkdir -p /opt/zammad/contrib/link/addons -COPY addons contrib/link/addons -COPY setup.rb contrib/link/setup.rb -COPY install.rb contrib/link/install.rb - -# Install system dependencies -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - git \ - && rm -rf /var/lib/apt/lists/* - -# Install Ruby gems (they should already be installed in the base image) -RUN bundle check || bundle install --jobs 8 - -# Install Node packages +# Install node modules +COPY .aidocs/zammad/package.json .aidocs/zammad/pnpm-lock.yaml ./ +COPY .aidocs/zammad/.eslint-plugin-zammad/ .eslint-plugin-zammad/ RUN pnpm install --frozen-lockfile -# CRITICAL: Install addons -# This extracts addon files including CoffeeScript, Vue components, TypeScript, and CSS +# Copy Zammad source +COPY .aidocs/zammad/ . + +# --- CDR Link Addon --- +RUN mkdir -p contrib/link/addons +COPY docker/zammad/addons/ contrib/link/addons/ +COPY docker/zammad/setup.rb contrib/link/setup.rb +COPY docker/zammad/install.rb contrib/link/install.rb RUN ruby contrib/link/install.rb -# Rebuild Vite frontend to include addon Vue components -# The base image has pre-built Vite assets, but addon Vue files need to be compiled -RUN RAILS_ENV=production bundle exec vite build --clobber +# OpenSearch compatibility: 'flattened' -> 'flat_object' +RUN sed -i "s/'flattened'/'flat_object'/g" lib/search_index_backend.rb -# Fix OpenSearch compatibility: Replace 'flattened' with 'flat_object' -# Elasticsearch uses 'flattened' but OpenSearch uses 'flat_object' -# Without this fix, search index creation fails with: -# [o.o.c.m.MetadataCreateIndexService] failed on parsing mappings on index creation -# org.opensearch.index.mapper.MapperParsingException: Failed to parse mapping [_doc]: -# No handler for type [flattened] declared on field [preferences] -# See: https://github.com/zammad/zammad/blob/bfd2f5befc3aec3fe607a5b6146788ec9af461e4/lib/search_index_backend.rb#L896 -RUN sed -i "s/'flattened'/'flat_object'/g" /opt/zammad/lib/search_index_backend.rb +# Build version info +ARG COMMIT_SHA="" +RUN COMMIT_SHA="${COMMIT_SHA:-$(git rev-parse HEAD 2>/dev/null || echo unknown)}"; \ + COMMIT_SHA_SHORT=$(echo "${COMMIT_SHA}" | cut -c 1-8); \ + echo "$(tr -d '\n' < VERSION)-${COMMIT_SHA_SHORT}.docker" > VERSION; \ + cat VERSION -# Precompile assets with addon CoffeeScript files included -# Use ZAMMAD_SAFE_MODE=1 and dummy DATABASE_URL to avoid needing real database +# Precompile all assets (Vite + Sprockets, including addon Vue/CoffeeScript) RUN touch db/schema.rb && \ ZAMMAD_SAFE_MODE=1 DATABASE_URL=postgresql://zammad:/zammad bundle exec rake assets:precompile -# Clean up build artifacts -RUN rm -rf tmp/cache node_modules/.cache -ARG EMBEDDED=false -ARG LINK_HOST=http://link:3000 -# Add nginx proxy configuration for embedded mode -# Insert location block before the final closing brace -RUN if [ "$EMBEDDED" = "true" ] ; then \ - sed -i '$ d' /opt/zammad/contrib/nginx/zammad.conf && \ - echo "" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo " location /link {" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo " set \$link_url ${LINK_HOST}; proxy_pass \$link_url;" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo " proxy_set_header Host \$host;" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo " proxy_set_header X-Real-IP \$remote_addr;" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo " proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo " proxy_set_header X-Forwarded-Proto https;" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo " }" >> /opt/zammad/contrib/nginx/zammad.conf && \ - echo "}" >> /opt/zammad/contrib/nginx/zammad.conf; \ -fi +RUN script/build/cleanup.sh +# Precompile bootsnap for faster boot times +RUN bundle exec bootsnap precompile --gemfile app/ lib/ -# Modify entrypoint to install packages and run migrations at runtime +# Inject addon registration into the entrypoint (runs during zammad-init) RUN sed -i '/^[[:space:]]*# es config/a\ echo "Installing addon packages..."\n\ bundle exec rails runner /opt/zammad/contrib/link/setup.rb\n\ bundle exec rake zammad:package:migrate\n\ - ' /docker-entrypoint.sh + ' bin/docker-entrypoint -FROM zammad/zammad-docker-compose:${ZAMMAD_VERSION} AS runner -USER root +# Nginx embedded mode: add /link proxy location +ARG EMBEDDED=false +ARG LINK_HOST=http://link:3000 +RUN if [ "$EMBEDDED" = "true" ] ; then \ + sed -i '$ d' contrib/nginx/zammad.conf && \ + echo "" >> contrib/nginx/zammad.conf && \ + echo " location /link {" >> contrib/nginx/zammad.conf && \ + echo " set \$link_url ${LINK_HOST}; proxy_pass \$link_url;" >> contrib/nginx/zammad.conf && \ + echo " proxy_set_header Host \$host;" >> contrib/nginx/zammad.conf && \ + echo " proxy_set_header X-Real-IP \$remote_addr;" >> contrib/nginx/zammad.conf && \ + echo " proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;" >> contrib/nginx/zammad.conf && \ + echo " proxy_set_header X-Forwarded-Proto https;" >> contrib/nginx/zammad.conf && \ + echo " }" >> contrib/nginx/zammad.conf && \ + echo "}" >> contrib/nginx/zammad.conf; \ +fi -# Install Node.js and npm in runner for asset compilation at runtime -# Using Node from Debian repository for simplicity -RUN apt-get update && \ - apt-get install -y --no-install-recommends nodejs npm && \ - rm -rf /var/lib/apt/lists/* && \ - npm install -g pnpm +# --- Final stage --- +FROM base -USER zammad -COPY --from=builder --chown=zammad:zammad ${ZAMMAD_DIR} ${ZAMMAD_DIR} -COPY --from=builder /usr/local/bundle /usr/local/bundle -COPY --from=builder /docker-entrypoint.sh /docker-entrypoint.sh +RUN apt-get update -qq && \ + apt-get upgrade -y && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + +ENV POSTGRESQL_DB=zammad_production \ + POSTGRESQL_HOST=postgresql \ + POSTGRESQL_PORT=5432 \ + POSTGRESQL_USER=zammad \ + POSTGRESQL_PASS=zammad \ + POSTGRESQL_OPTIONS=?pool=50 \ + RAILS_TRUSTED_PROXIES=127.0.0.1,::1 + +RUN groupadd --system --gid 1000 zammad && \ + useradd --create-home --home /opt/zammad --shell /bin/bash --uid 1000 --gid 1000 zammad + +RUN sed -i -e "s#user www-data;##g" \ + -e 's#/var/log/nginx/\(access\|error\).log#/dev/stdout#g' \ + -e 's#pid /run/nginx.pid;#pid /tmp/nginx.pid;#g' /etc/nginx/nginx.conf && \ + mkdir -p /opt/zammad /var/log/nginx + +RUN mkdir -p "/opt/zammad/storage" "/opt/zammad/tmp" && \ + chown -R 1000:1000 /etc/nginx /var/lib/nginx /var/log/nginx /opt/zammad + +COPY --chown=1000:1000 --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}" +COPY --chown=1000:1000 --from=build /opt/zammad /opt/zammad + +# Backwards compatibility +RUN ln -s "/opt/zammad/bin/docker-entrypoint" /docker-entrypoint.sh + +USER 1000:1000 +ENTRYPOINT ["/opt/zammad/bin/docker-entrypoint"] +LABEL io.portainer.commands.rails-console="bundle exec rails c" diff --git a/packages/zammad-addon-link/src/app/assets/javascripts/app/controllers/_profile/notification.coffee b/packages/zammad-addon-link/src/app/assets/javascripts/app/controllers/_profile/notification.coffee index 8a2c7f6..3156b6f 100644 --- a/packages/zammad-addon-link/src/app/assets/javascripts/app/controllers/_profile/notification.coffee +++ b/packages/zammad-addon-link/src/app/assets/javascripts/app/controllers/_profile/notification.coffee @@ -98,7 +98,7 @@ class ProfileNotification extends App.ControllerSubContent groups = _.sortBy(groups, (item) -> return item.name) for sound in @sounds - sound.selected = sound.file is App.OnlineNotification.soundFile() ? true : false + sound.selected = sound.file is App.OnlineNotification.soundFile() signal_notification_enabled = App.Config.get('signal_notification_enabled') diff --git a/packages/zammad-addon-link/src/app/frontend/apps/desktop/components/Form/fields/FieldNotifications/FieldNotificationsInput.vue b/packages/zammad-addon-link/src/app/frontend/apps/desktop/components/Form/fields/FieldNotifications/FieldNotificationsInput.vue index 1c269a8..f19f599 100644 --- a/packages/zammad-addon-link/src/app/frontend/apps/desktop/components/Form/fields/FieldNotifications/FieldNotificationsInput.vue +++ b/packages/zammad-addon-link/src/app/frontend/apps/desktop/components/Form/fields/FieldNotifications/FieldNotificationsInput.vue @@ -1,4 +1,4 @@ - +