Orchestrata Ultimate / Specs / 018-fireflies-integration
018-fireflies-integration: Fireflies Integration
The Fireflies Integration is a VizInt Command Center gadget that brings meeting intelligence from Fireflies.ai into the Orchestrata dashboard. It displays recent meeting transcripts, enables keyword search across all meetings, shows AI-generated meeting summaries, and links meeting notes to orchestrata sessions and iterations. The gadget connects to the Fireflies API via REST calls from the browser and optionally through a Python-side MCP bridge for server-side API access.
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/018-fireflies-integration/ |
| Status line in the spec | Draft |
| Requirement IDs defined | 80 |
With a @traces citation in src/ |
12 (15.0%) |
With a @traces citation in tests/ |
0 (0.0%) |
| Tracked files | 6 |
| RTM page | 018-fireflies-integration |
Reading this spec
The Fireflies Integration is a VizInt Command Center gadget that brings content from the Fireflies.ai service into the Orchestrata dashboard, so that it can be read, searched and linked to orchestration work without leaving the Command Center. The spec's aim is traceability: material from the service is linked to specific sessions and iterations.
The scope is six user stories: listing recent items, searching by keyword, displaying summaries, linking items to sessions and iterations, configuring the connection, and a server-side bridge for access when the browser is restricted. The functional groups are listing, keyword search, summaries, session linking and bridge integration. Requirement IDs use the REQ-018- prefix.
The design is a browser-side JavaScript gadget calling the Fireflies REST API, with an optional Python-side MCP bridge (FirefliesMCPBridge) for server-side access when browser CORS is restrictive. Session and iteration links are stored locally and optionally synchronized to the gateway through State Sync. The gadget registers with the Command Center through a GadgetManifest in the productivity category.
In the code, the Python side is in orchestrata_ultimate/session/fireflies_tools, orchestrata_ultimate/integrations/fireflies_client and orchestrata_ultimate/gateway/handlers/fireflies. The per-requirement view is on the RTM page.
The spec's status line reads Draft. It tracks 6 files and defines 80 requirement IDs. The full text follows below.
Measured coverage is 12 of 80 requirements cited by at least one @traces in src/ (15.0%), spread over 3 modules; the module citing the most of them is orchestrata_ultimate/session/fireflies_tools (10 requirements). In tests/, 0 requirements are cited by a test-side @traces.
Coverage gaps: 68 requirements have no citing symbol. The largest untraced groups are REQ-018-* (68). Untraced means no @traces names the ID; the behaviour may still exist in code that was never annotated. Test-side citations are thinner than code-side ones (0 against 12).
Requirements
Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.
| ID | Done | Requirement | Traced by |
|---|---|---|---|
REQ-018-001 |
no | Gadget displays a scrollable list of recent meetings | none |
REQ-018-002 |
no | Each entry shows: title, date, duration, participant count | none |
REQ-018-003 |
no | List sorted by date descending (most recent first) | none |
REQ-018-004 |
no | Pagination loads 20 transcripts per page | none |
REQ-018-005 |
no | Infinite scroll triggers next page load at bottom | none |
REQ-018-006 |
no | Clicking a meeting entry expands to show the full transcript | none |
REQ-018-007 |
no | Transcript text formatted with speaker labels and timestamps | none |
REQ-018-008 |
no | Long transcripts (> 100,000 chars) lazy-loaded in chunks | none |
REQ-018-009 |
no | Speaker segments visually differentiated by color | none |
REQ-018-010 |
no | Collapsing a transcript preserves scroll position in list | none |
REQ-018-011 |
no | Last sync timestamp displayed in gadget header | none |
REQ-018-012 |
no | Manual refresh button re-fetches transcript list | 1 |
REQ-018-013 |
no | Auto-refresh every 10 minutes (configurable) | none |
REQ-018-014 |
no | Cached transcripts served when API is unavailable | none |
REQ-018-015 |
no | Loading skeleton shown during initial fetch | none |
REQ-018-016 |
no | Search input field in gadget header | none |
REQ-018-017 |
no | Search debounced at 300ms (configurable) | none |
REQ-018-018 |
no | Search results replace transcript list view | none |
REQ-018-019 |
no | Empty search returns to recent meetings list | none |
REQ-018-020 |
no | Each result shows: meeting title, date, matching excerpt | none |
REQ-018-021 |
no | Keywords highlighted in excerpts with <mark> elements |
none |
REQ-018-022 |
no | Excerpt shows 100 characters before and after the match | none |
REQ-018-023 |
no | Results ranked by relevance (match count) | none |
REQ-018-024 |
no | Results paginated (20 per page) | none |
REQ-018-025 |
no | Multi-word queries supported | none |
REQ-018-026 |
no | Last 10 search queries stored in localStorage | none |
REQ-018-027 |
no | Search history accessible via dropdown on focus | none |
REQ-018-028 |
no | Clicking a history entry re-executes the search | none |
REQ-018-029 |
no | Search history clearable from settings | none |
REQ-018-030 |
no | Total result count displayed in header | none |
REQ-018-031 |
no | Each meeting has "Transcript" and "Summary" tabs | none |
REQ-018-032 |
no | Summary tab shows: key topics, action items, decisions, follow-ups | none |
REQ-018-033 |
no | Each summary section is collapsible | none |
REQ-018-034 |
no | Action items displayed as a checklist (read-only) | none |
REQ-018-035 |
no | Decisions displayed as a bullet list | none |
REQ-018-036 |
no | Summary fetched on first tab switch (not on list load) | none |
REQ-018-037 |
no | Loading skeleton shown while fetching | none |
REQ-018-038 |
no | Fetched summaries cached for session duration | none |
REQ-018-039 |
no | "Summary not available" displayed for unprocessed meetings | none |
REQ-018-040 |
no | Manual refresh button re-fetches summary | none |
REQ-018-041 |
no | "Link to Session" button on each meeting entry | none |
REQ-018-042 |
no | Session selector shows recent sessions from session.list RPC |
none |
REQ-018-043 |
no | Each session option shows: number, purpose, date | none |
REQ-018-044 |
no | Optional iteration number selector within session | none |
REQ-018-045 |
no | Meeting linkable to multiple sessions | none |
REQ-018-046 |
no | Linked sessions shown as tags on meeting entry | none |
REQ-018-047 |
no | Tag includes session number and purpose excerpt | none |
REQ-018-048 |
no | Clicking tag navigates to session in session-manager gadget | none |
REQ-018-049 |
no | Remove link via tag context menu (x button) | none |
REQ-018-050 |
no | Linked meeting count visible in session-manager gadget detail view | none |
REQ-018-051 |
no | Links stored in localStorage under commandcenter.state.fireflies.session_links |
none |
REQ-018-052 |
no | Links synced to gateway via State Sync | none |
REQ-018-053 |
no | fireflies.meeting.linked event emitted on ctx.bus |
none |
REQ-018-054 |
no | fireflies.meeting.unlinked event emitted on removal |
none |
REQ-018-055 |
no | Duplicate links prevented (idempotent) | none |
REQ-018-056 |
no | Settings panel with API key input field | none |
REQ-018-057 |
no | API key encrypted with AES-GCM via Web Crypto API | none |
REQ-018-058 |
no | "Test Connection" button validates API key | 2 |
REQ-018-059 |
no | Connection status indicator: green/yellow/red | none |
REQ-018-060 |
no | Clear instructions for obtaining Fireflies API key | none |
REQ-018-061 |
no | Toggle between browser-direct and MCP bridge mode | none |
REQ-018-062 |
no | MCP bridge URL input visible when bridge mode selected | none |
REQ-018-063 |
no | Browser-direct mode is default | none |
REQ-018-064 |
no | Mode change triggers reconnection test | none |
REQ-018-065 |
no | Settings persisted in localStorage | none |
REQ-018-066 |
no | fireflies.transcripts RPC method returns transcript list |
5 |
REQ-018-067 |
no | fireflies.transcript RPC method returns single transcript with full text |
5 |
REQ-018-068 |
no | fireflies.search RPC method returns search results |
5 |
REQ-018-069 |
no | fireflies.summary RPC method returns meeting summary |
5 |
REQ-018-070 |
no | All methods require read_only gateway scope minimum | 1 |
REQ-018-071 |
no | MCP bridge implemented as SPEC-015 plugin | none |
REQ-018-072 |
no | Plugin uses existing Fireflies MCP tools | 1 |
REQ-018-073 |
no | Plugin authenticates with server-side Fireflies API key | 4 |
REQ-018-074 |
no | Plugin caches responses for 10 minutes (configurable) | 2 |
REQ-018-075 |
no | Plugin respects Fireflies API rate limits | 1 |
REQ-018-076 |
no | If MCP bridge unreachable, gadget falls back to browser-direct mode | none |
REQ-018-077 |
no | Fallback requires local API key to be configured | none |
REQ-018-078 |
no | User notified of fallback via connection status indicator | none |
REQ-018-079 |
no | Bridge reconnection attempted periodically (every 60s) | none |
REQ-018-080 |
no | Bridge health checked via gateway RPC | 2 |
Code that traces this spec
| Module | Symbols | Requirements |
|---|---|---|
orchestrata_ultimate/gateway/handlers/fireflies |
7 | 7 |
orchestrata_ultimate/integrations/fireflies_client |
7 | 7 |
orchestrata_ultimate/session/fireflies_tools |
8 | 10 |
Checklists
checklists/README.md
Fireflies Integration Checklists
Project: Orchestrata Fireflies Integration (Spec 018) Component: Fireflies Gadget + MCP Bridge Status: Planning Phase Owner: Architecture Team
Overview
The Fireflies Integration is a VizInt Command Center gadget that brings meeting intelligence from Fireflies.ai into the Orchestrata dashboard. It displays meeting transcripts, enables keyword search, shows AI-generated summaries, and links meeting notes to orchestrata sessions and iterations. The gadget supports browser-direct API access and an optional Python-side MCP bridge for server-side API access.
Checklist Summary
| Checklist | Total Items | Completed | Progress |
|---|---|---|---|
| Requirements | 80+ | 0 | 0% |
| Constitutional Compliance | 55+ | 0 | 0% |
| Testing Plan | 130+ | 0 | 0% |
| TOTAL | 265+ | 0 | 0% |
Key Responsibilities
1. Transcript Display
- Fetch and display recent meeting transcripts from Fireflies API
- Format transcripts with speaker labels and timestamps
- Support pagination and lazy loading for large transcripts
2. Meeting Search
- Keyword search across all meeting transcripts
- Highlight matching keywords in excerpts
- Rank results by relevance
3. Meeting Summaries
- Display AI-generated meeting summaries
- Structured sections: topics, action items, decisions, follow-ups
- Cache summaries for session duration
4. Session Linking
- Link meetings to orchestrata sessions and iterations
- Bidirectional visibility (Fireflies gadget and session-manager gadget)
- Persistent links via localStorage and State Sync
5. MCP Bridge (Optional)
- Python-side plugin for server-side Fireflies API access
- Gateway RPC methods under
fireflies.*namespace - Fallback to browser-direct mode when bridge unavailable
Performance Targets
| Metric | Target | Critical Threshold |
|---|---|---|
| Transcript List Fetch | < 2s P95 | < 4s P99 |
| Search Query | < 3s P95 | < 5s P99 |
| Summary Fetch | < 2s P95 | < 4s P99 |
| Transcript Render (50K chars) | < 200ms | < 500ms |
| Cache Hit | < 10ms | < 50ms |
| MCP Bridge Round-Trip | < 4s P95 | < 6s P99 |
| Memory Usage (20 transcripts) | < 15MB | < 25MB |
Checklist Files
1. requirements.md
Functional requirements organized by user stories:
- US-001: View Recent Meeting Transcripts
- US-002: Search Across Meetings
- US-003: Display Meeting Summaries
- US-004: Link Meetings to Sessions and Iterations
- US-005: Configure Fireflies Connection
- US-006: MCP Bridge for Server-Side Access
2. constitutional.md
Compliance with all 11 constitutional articles covering agent autonomy, Prolog governance, session isolation, extensibility, testing standards, observability, graceful degradation, and versioning.
3. testing.md
Comprehensive testing strategy:
- Unit Tests (55+ tests): Transcript list, search, summaries, session linker, API provider, credentials
- Integration Tests (35+ tests): Fireflies REST API, MCP bridge, session linking, credentials
- E2E Tests (25+ tests): Full browser workflows via Playwright
- Performance Tests (15+ tests): API latency, render time, memory
Integration Points
Upstream Dependencies
- Fireflies.ai REST API (GraphQL at api.fireflies.ai/graphql)
- Fireflies MCP tools (fireflies_get_transcript, fireflies_search, fireflies_get_summary, fireflies_get_transcripts)
- SPEC-016 VizInt Command Center (GadgetBridge, ctx.bus, StateSync)
- SPEC-014 WebSocket Gateway (MCP bridge RPC routing)
- SPEC-015 Plugin SDK (MCP bridge plugin)
Downstream Consumers
- Session Manager gadget (meeting-session link visibility)
- Notification Center (API connection failure alerts)
Dependencies
Required APIs
- Fireflies.ai GraphQL API
Required Libraries
- VizInt portal framework (gadget lifecycle)
- Web Crypto API (credential encryption)
Optional Services
- SPEC-014 WebSocket Gateway (for MCP bridge mode)
- SPEC-015 Plugin SDK (for MCP bridge plugin)
References
- SPEC-014: WebSocket Gateway
- SPEC-015: Plugin SDK
- SPEC-016: VizInt Command Center
- SPEC-017: Calendar Integration
- Fireflies.ai API Documentation
Last Updated: 2026-03-28 Version: 1.0.0 Maintained By: Architecture Team
checklists/constitutional.md
Fireflies Integration - Constitutional Compliance
Component: Fireflies Gadget Spec: 018-fireflies-integration Status: Compliance Review Total Compliance Items: 55+
Overview
This document tracks compliance of the Fireflies Integration gadget with the Orchestrata Constitution. As a browser-side productivity gadget with an optional Python MCP bridge, the Fireflies integration must meet security, observability, and extensibility requirements while maintaining data privacy for meeting transcripts.
Article I: Agent Autonomy
Principle: Agents retain autonomy; gadgets observe and assist without interference.
Compliance Requirements
- [ ] CONST-I-001: Fireflies gadget does not inject or modify CXP messages
- [ ] CONST-I-002: Meeting-session links are metadata only, no influence on agent decisions
- [ ] CONST-I-003: Transcript data does not influence Volk routing or task assignment
- [ ] CONST-I-004: Gadget operates independently of agent decision-making
- [ ] CONST-I-005: MCP bridge observes API data only, does not control system behavior
Priority: Medium Verification: Code review + integration tests
Article II: Prolog as Single Source of Truth
Principle: Governance rules defined in Prolog.
Compliance Requirements
- [ ] CONST-II-001: MCP bridge RPC methods authorized via gateway Prolog rules
- [ ] CONST-II-002: No hardcoded access control logic in gadget or bridge
- [ ] CONST-II-003: Gateway scope enforcement respected for all RPC calls
- [ ] CONST-II-004: Meeting-session link creation respects session ownership from gateway
- [ ] CONST-II-005: Bridge plugin authorization via
plugin_allowedpredicate
Priority: Medium Verification: Integration tests
Article III: Session Isolation
Principle: Sessions are isolated; state does not leak between sessions.
Compliance Requirements
- [ ] CONST-III-001: Meeting-session links scoped by session ID (no cross-session leakage)
- [ ] CONST-III-002: Session selector shows only sessions accessible to the authenticated user
- [ ] CONST-III-003: Links stored with explicit session_id, not derived from context
- [ ] CONST-III-004: Multi-user environments scope links by gateway client_id
- [ ] CONST-III-005: Transcript data not associated with sessions unless explicitly linked
Priority: High Verification: Integration tests
Article IV: Hooks for Extensibility
Principle: Extension points for customization without core modification.
Compliance Requirements
- [ ] CONST-IV-001: Fireflies provider interface allows adding alternative meeting platforms
- [ ] CONST-IV-002: Link schema extensible with additional metadata fields
- [ ] CONST-IV-003: Gadget configuration schema allows future property additions
- [ ] CONST-IV-004: MCP bridge plugin extensible with additional methods
- [ ] CONST-IV-005: ctx.bus events allow other gadgets to react to meeting links
Priority: Medium Verification: Architecture review
Article V: Minimal Core, Maximal Extension
Principle: Core is minimal; features added via extensions.
Compliance Requirements
- [ ] CONST-V-001: Fireflies gadget is a standalone extension, not embedded in core
- [ ] CONST-V-002: MCP bridge is an optional SPEC-015 plugin
- [ ] CONST-V-003: No Fireflies logic in core Command Center code
- [ ] CONST-V-004: Gadget loadable/unloadable without affecting other gadgets
- [ ] CONST-V-005: Browser-direct mode operates without any backend dependencies
Priority: High Verification: Architecture review
Article VI: Implementation Standards
Principle: JavaScript ES2024 (browser) and Python 3.14t (bridge).
Compliance Requirements
- [ ] CONST-VI-001: ES2024 module syntax for browser code
- [ ] CONST-VI-002: Async/await for all API calls
- [ ] CONST-VI-003: JSDoc comments for all public JavaScript functions
- [ ] CONST-VI-004: Type hints for all public Python functions (bridge)
- [ ] CONST-VI-005: Google-style docstrings for Python bridge classes
Priority: High Verification: Code review + linting
Article VII: Testing Without Mocks
Principle: Tests use real implementations.
Compliance Requirements
- [ ] CONST-VII-001: Tests use real DOM via JSDOM or Playwright
- [ ] CONST-VII-002: API tests use real Fireflies API (test account)
- [ ] CONST-VII-003: No mock objects for WebSocket, fetch, or localStorage
- [ ] CONST-VII-004: MCP bridge tests use real gateway and plugin system
- [ ] CONST-VII-005: E2E tests use real browser via Playwright
Priority: Critical Verification: Test code review
Article VIII: Metrics and Observability
Principle: All operations observable and measurable.
Compliance Requirements
- [ ] CONST-VIII-001: API call latency logged for each provider
- [ ] CONST-VIII-002: Cache hit/miss ratio trackable
- [ ] CONST-VIII-003: Search query timing logged
- [ ] CONST-VIII-004: Link creation/deletion events logged
- [ ] CONST-VIII-005: MCP bridge request metrics exposed (if bridge enabled)
Priority: Medium Verification: Log review + observability tests
Article IX: Graceful Degradation
Principle: System degrades gracefully under failure.
Compliance Requirements
- [ ] CONST-IX-001: Cached transcripts visible when Fireflies API unreachable
- [ ] CONST-IX-002: MCP bridge fallback to browser-direct mode on failure
- [ ] CONST-IX-003: Search disabled gracefully in offline mode
- [ ] CONST-IX-004: Link persistence survives API and gateway outages
- [ ] CONST-IX-005: Invalid API key produces clear error, not gadget crash
Priority: High Verification: Failure injection tests
Article X: Version Compatibility
Principle: APIs are versioned; breaking changes avoided.
Compliance Requirements
- [ ] CONST-X-001: Gadget manifest declares min_api_version
- [ ] CONST-X-002: MCP bridge RPC methods namespaced (fireflies.*)
- [ ] CONST-X-003: Link schema versioned for backward compatibility
- [ ] CONST-X-004: Bridge plugin declares min_orchestrata_version
- [ ] CONST-X-005: Gadget settings schema additive-only for new versions
Priority: Medium Verification: Compatibility tests
Article XI: Documentation First
Principle: Documentation precedes implementation.
Compliance Requirements
- [ ] CONST-XI-001: Specification written before implementation
- [ ] CONST-XI-002: Fireflies API integration documented
- [ ] CONST-XI-003: MCP bridge plugin manifest documented
- [ ] CONST-XI-004: Configuration options documented
- [ ] CONST-XI-005: Meeting-session link schema documented
Priority: High Verification: Documentation review
Summary Statistics
| Article | Total Items | Completed | Percentage |
|---|---|---|---|
| Article I (Autonomy) | 5 | 0 | 0% |
| Article II (Prolog) | 5 | 0 | 0% |
| Article III (Isolation) | 5 | 0 | 0% |
| Article IV (Hooks) | 5 | 0 | 0% |
| Article V (Minimal Core) | 5 | 0 | 0% |
| Article VI (Implementation) | 5 | 0 | 0% |
| Article VII (No Mocks) | 5 | 0 | 0% |
| Article VIII (Observability) | 5 | 0 | 0% |
| Article IX (Degradation) | 5 | 0 | 0% |
| Article X (Versioning) | 5 | 0 | 0% |
| Article XI (Documentation) | 5 | 0 | 0% |
| TOTAL | 55 | 0 | 0% |
Last Updated: 2026-03-28 Version: 1.0.0 Maintained By: Architecture Team
checklists/requirements.md
The requirement list above comes from this file; 0 of 80 checkbox items are ticked.
checklists/testing.md
Fireflies Integration - Testing Plan
Component: Fireflies Gadget Spec: 018-fireflies-integration Status: Test Planning Phase Total Test Cases: 130+
Overview
This document defines the testing strategy for the Fireflies Integration gadget. All tests follow the strict "no mocking" policy. Unit tests use JSDOM for real DOM interaction, integration tests use real Fireflies API (test account), and E2E tests use Playwright with a real browser.
Test Categories Summary
| Category | Test Count | Purpose | Priority |
|---|---|---|---|
| Unit Tests | 55+ | Core logic validation | Critical |
| Integration Tests | 35+ | API and system integration | Critical |
| E2E Tests | 25+ | Full browser workflow | High |
| Performance Tests | 15+ | Latency and rendering | High |
| TOTAL | 130+ |
Unit Tests (55+)
Transcript List (10 tests)
- [ ] TEST-UNIT-TL-001: Transcript list renders with meeting title, date, duration
- [ ] TEST-UNIT-TL-002: List sorted by date descending
- [ ] TEST-UNIT-TL-003: Pagination triggers next page load at scroll bottom
- [ ] TEST-UNIT-TL-004: Loading skeleton displayed during fetch
- [ ] TEST-UNIT-TL-005: Empty state displayed when no transcripts
- [ ] TEST-UNIT-TL-006: Expanding entry shows full transcript
- [ ] TEST-UNIT-TL-007: Speaker labels colored by speaker
- [ ] TEST-UNIT-TL-008: Long transcripts lazy-loaded in chunks
- [ ] TEST-UNIT-TL-009: Collapsing entry returns to list view
- [ ] TEST-UNIT-TL-010: Last sync timestamp displayed correctly
Search Panel (10 tests)
- [ ] TEST-UNIT-SR-001: Search input debounces at configured interval
- [ ] TEST-UNIT-SR-002: Search results replace list view
- [ ] TEST-UNIT-SR-003: Keywords highlighted with
<mark>elements - [ ] TEST-UNIT-SR-004: Excerpts show context around match
- [ ] TEST-UNIT-SR-005: Results ranked by match count
- [ ] TEST-UNIT-SR-006: Empty search returns to list view
- [ ] TEST-UNIT-SR-007: Multi-word queries submitted correctly
- [ ] TEST-UNIT-SR-008: Search history stored in localStorage
- [ ] TEST-UNIT-SR-009: History dropdown appears on focus
- [ ] TEST-UNIT-SR-010: Total result count displayed
Summary Panel (10 tests)
- [ ] TEST-UNIT-SM-001: Summary tab visible on each meeting entry
- [ ] TEST-UNIT-SM-002: Summary fetched on first tab switch
- [ ] TEST-UNIT-SM-003: Topics section rendered with titles and summaries
- [ ] TEST-UNIT-SM-004: Action items rendered as checklist
- [ ] TEST-UNIT-SM-005: Decisions rendered as bullet list
- [ ] TEST-UNIT-SM-006: Follow-ups rendered as bullet list
- [ ] TEST-UNIT-SM-007: Sections collapsible
- [ ] TEST-UNIT-SM-008: Loading skeleton during fetch
- [ ] TEST-UNIT-SM-009: "Summary not available" for unprocessed meetings
- [ ] TEST-UNIT-SM-010: Cached summary served on subsequent views
Session Linker (10 tests)
- [ ] TEST-UNIT-LK-001: "Link to Session" opens session selector
- [ ] TEST-UNIT-LK-002: Session selector populated from session.list RPC
- [ ] TEST-UNIT-LK-003: Session options show number, purpose, date
- [ ] TEST-UNIT-LK-004: Optional iteration number input available
- [ ] TEST-UNIT-LK-005: Link stored in localStorage
- [ ] TEST-UNIT-LK-006: Linked sessions shown as tags on meeting entry
- [ ] TEST-UNIT-LK-007: Tag click emits navigation event on ctx.bus
- [ ] TEST-UNIT-LK-008: Tag removal emits unlink event on ctx.bus
- [ ] TEST-UNIT-LK-009: Duplicate link prevented (idempotent)
- [ ] TEST-UNIT-LK-010: Multiple sessions linkable to one meeting
API Provider (10 tests)
- [ ] TEST-UNIT-AP-001: BrowserProvider constructs correct GraphQL request
- [ ] TEST-UNIT-AP-002: BrowserProvider sets Authorization header
- [ ] TEST-UNIT-AP-003: MCPProvider routes through GadgetBridge RPC
- [ ] TEST-UNIT-AP-004: Provider fallback: MCP unavailable switches to browser
- [ ] TEST-UNIT-AP-005: Response parsed to FirefliesTranscript objects
- [ ] TEST-UNIT-AP-006: Rate limit response triggers backoff
- [ ] TEST-UNIT-AP-007: Network error returns cached data
- [ ] TEST-UNIT-AP-008: Cache TTL respected (expired cache triggers fetch)
- [ ] TEST-UNIT-AP-009: Concurrent requests for same data coalesced
- [ ] TEST-UNIT-AP-010: Invalid API key detected on first call
Credential Management (5 tests)
- [ ] TEST-UNIT-CR-001: API key encrypted with AES-GCM before storage
- [ ] TEST-UNIT-CR-002: Encrypted key decryptable on next load
- [ ] TEST-UNIT-CR-003: Missing Web Crypto API triggers plain text fallback with warning
- [ ] TEST-UNIT-CR-004: Test connection validates API key
- [ ] TEST-UNIT-CR-005: Clear credentials removes all stored data
Integration Tests (35+)
Fireflies REST API (10 tests)
- [ ] TEST-INTEG-API-001: Transcript list fetched with valid API key
- [ ] TEST-INTEG-API-002: Single transcript fetched with full text and speakers
- [ ] TEST-INTEG-API-003: Search returns relevant results for known keywords
- [ ] TEST-INTEG-API-004: Summary fetched for a processed transcript
- [ ] TEST-INTEG-API-005: Invalid API key returns authentication error
- [ ] TEST-INTEG-API-006: Rate limit handling with retry-after
- [ ] TEST-INTEG-API-007: GraphQL pagination returns correct pages
- [ ] TEST-INTEG-API-008: Empty search returns zero results gracefully
- [ ] TEST-INTEG-API-009: Large transcript (100K+ chars) handled correctly
- [ ] TEST-INTEG-API-010: API timeout handled without crash
MCP Bridge Integration (10 tests)
- [ ] TEST-INTEG-MCP-001: Bridge plugin loaded via SPEC-015 plugin manager
- [ ] TEST-INTEG-MCP-002:
fireflies.transcriptsRPC returns transcript list - [ ] TEST-INTEG-MCP-003:
fireflies.transcriptRPC returns full transcript - [ ] TEST-INTEG-MCP-004:
fireflies.searchRPC returns search results - [ ] TEST-INTEG-MCP-005:
fireflies.summaryRPC returns meeting summary - [ ] TEST-INTEG-MCP-006: Bridge caches responses (same request within TTL returns cache)
- [ ] TEST-INTEG-MCP-007: Bridge respects gateway scope authorization
- [ ] TEST-INTEG-MCP-008: Bridge handles Fireflies API errors gracefully
- [ ] TEST-INTEG-MCP-009: Bridge plugin unload cleans up registered methods
- [ ] TEST-INTEG-MCP-010: Bridge plugin audit trail records RPC calls
Session Linking Integration (10 tests)
- [ ] TEST-INTEG-LINK-001: Session.list RPC returns sessions for selector
- [ ] TEST-INTEG-LINK-002: Link created and stored in localStorage
- [ ] TEST-INTEG-LINK-003: Link synced to gateway via State Sync
- [ ] TEST-INTEG-LINK-004: ctx.bus event emitted on link creation
- [ ] TEST-INTEG-LINK-005: ctx.bus event emitted on link removal
- [ ] TEST-INTEG-LINK-006: Session-manager gadget receives link event
- [ ] TEST-INTEG-LINK-007: Links persist across page reload
- [ ] TEST-INTEG-LINK-008: Links scoped by gateway client_id
- [ ] TEST-INTEG-LINK-009: Stale session references detected (session not found)
- [ ] TEST-INTEG-LINK-010: Concurrent link operations handled without race conditions
Credential Integration (5 tests)
- [ ] TEST-INTEG-CRED-001: API key encryption round-trip with Web Crypto API
- [ ] TEST-INTEG-CRED-002: Key derivation consistent across page reloads
- [ ] TEST-INTEG-CRED-003: Encrypted key stored and retrieved from localStorage
- [ ] TEST-INTEG-CRED-004: Test connection validates against real Fireflies API
- [ ] TEST-INTEG-CRED-005: Mode switch between browser-direct and MCP bridge seamless
E2E Tests (25+)
- [ ] TEST-E2E-001: Full flow: configure API key, view transcripts, search, view summary
- [ ] TEST-E2E-002: Search flow: type keyword, see results with highlights, expand transcript
- [ ] TEST-E2E-003: Summary flow: expand meeting, switch to summary tab, view sections
- [ ] TEST-E2E-004: Link flow: link meeting to session, verify tag appears
- [ ] TEST-E2E-005: Unlink flow: remove session tag, verify link removed
- [ ] TEST-E2E-006: Pagination: scroll to load more transcripts
- [ ] TEST-E2E-007: Offline: disconnect network, verify cached data visible
- [ ] TEST-E2E-008: Reconnect: restore network, verify new data fetched
- [ ] TEST-E2E-009: Theme toggle: dark/light mode applies to Fireflies gadget
- [ ] TEST-E2E-010: Resize: gadget resizes without layout breakage
- [ ] TEST-E2E-011: Page reload: API key and links persist
- [ ] TEST-E2E-012: Invalid API key: error shown with guidance
- [ ] TEST-E2E-013: MCP bridge mode: configure and verify RPC routing
- [ ] TEST-E2E-014: MCP fallback: bridge unavailable, switches to browser-direct
- [ ] TEST-E2E-015: Multiple gadgets: Fireflies coexists with CXP feed and calendar
- [ ] TEST-E2E-016: Session selector: list populated from gateway
- [ ] TEST-E2E-017: Iteration link: link meeting to specific iteration
- [ ] TEST-E2E-018: Search history: recent queries appear in dropdown
- [ ] TEST-E2E-019: Long transcript: lazy loading on scroll verified
- [ ] TEST-E2E-020: Speaker labels: different colors per speaker
- [ ] TEST-E2E-021: Action items: displayed as read-only checklist
- [ ] TEST-E2E-022: Decisions list: displayed as bullet points
- [ ] TEST-E2E-023: Settings panel: all configuration options functional
- [ ] TEST-E2E-024: Connection test: validates API key in real-time
- [ ] TEST-E2E-025: Manual refresh: re-fetches data from API
Performance Tests (15+)
- [ ] TEST-PERF-001: Transcript list fetch < 2s P95 for 20 transcripts
- [ ] TEST-PERF-002: Search query response < 3s P95
- [ ] TEST-PERF-003: Summary fetch < 2s P95
- [ ] TEST-PERF-004: Full transcript render (50K chars) < 200ms
- [ ] TEST-PERF-005: Cache hit retrieval < 10ms
- [ ] TEST-PERF-006: MCP bridge RPC round-trip < 4s P95
- [ ] TEST-PERF-007: Search highlight rendering < 100ms
- [ ] TEST-PERF-008: Gadget memory usage < 15MB with 20 cached transcripts
- [ ] TEST-PERF-009: No memory leak after 50 expand/collapse cycles
- [ ] TEST-PERF-010: Pagination scroll does not cause frame drops
- [ ] TEST-PERF-011: Session selector loads < 500ms
- [ ] TEST-PERF-012: Link creation < 100ms (localStorage write)
- [ ] TEST-PERF-013: Search debounce prevents excessive API calls
- [ ] TEST-PERF-014: Lazy loading chunks render < 100ms each
- [ ] TEST-PERF-015: Theme toggle applies to gadget < 100ms
Summary Statistics
| Category | Test Count | Completed | Percentage |
|---|---|---|---|
| Unit Tests | 55 | 0 | 0% |
| Integration Tests | 35 | 0 | 0% |
| E2E Tests | 25 | 0 | 0% |
| Performance Tests | 15 | 0 | 0% |
| TOTAL | 130 | 0 | 0% |
Last Updated: 2026-03-28 Version: 1.0.0 Maintained By: Architecture Team
Other tracked files
specs/018-fireflies-integration/compliance-audit.md
Full spec text
Verbatim from specs/018-fireflies-integration/spec.md; headings are pushed down two levels.
SPEC-018: Fireflies Integration
Metadata
- Spec ID: 018-fireflies-integration
- Title: Fireflies Integration
- Author: Mohamed
- Status: Draft
- Created: 2026-03-28
- Last Updated: 2026-03-28
- Priority: P2
- Version: 1.0.0
Overview
What
The Fireflies Integration is a VizInt Command Center gadget that brings meeting intelligence from Fireflies.ai into the Orchestrata dashboard. It displays recent meeting transcripts, enables keyword search across all meetings, shows AI-generated meeting summaries, and links meeting notes to orchestrata sessions and iterations. The gadget connects to the Fireflies API via REST calls from the browser and optionally through a Python-side MCP bridge for server-side API access.
Why
- Orchestrata development sessions are often preceded or followed by meetings where decisions, requirements, and action items are discussed — these meeting insights are disconnected from the orchestration workflow
- Meeting transcripts contain technical decisions, architectural choices, and requirement clarifications that should be linked to specific sessions and iterations for traceability
- Searching across meeting transcripts for specific topics (e.g., "gateway authentication", "plugin sandboxing") requires switching to the Fireflies web app, breaking the Command Center workflow
- AI-generated meeting summaries provide concise decision logs that complement session achievements in context.json
- The Fireflies MCP tools are already available (fireflies_get_transcript, fireflies_search, fireflies_get_summary, fireflies_get_transcripts) and can be leveraged for both browser and server-side access
How
- Browser-side JavaScript gadget with Fireflies REST API integration
- API key authentication stored in localStorage (encrypted)
- Recent transcripts fetched via
fireflies_get_transcriptsequivalent REST endpoint - Keyword search via
fireflies_searchequivalent REST endpoint - Meeting summaries via
fireflies_get_summaryequivalent REST endpoint - Optional Python-side MCP bridge (
FirefliesMCPBridge) for server-side access when browser CORS is restrictive - Session/iteration linking stored in localStorage and optionally synced via State Sync to the gateway
- Registers as a Command Center gadget via GadgetManifest with
category: "productivity"
User Scenarios & Stories
US-001: View Recent Meeting Transcripts
As a developer using the Command Center I want to see my recent meeting transcripts in a list So that I can quickly reference what was discussed without leaving the dashboard
Priority: P0
Acceptance Criteria:
- [ ] Gadget displays a list of recent meetings with title, date, duration, and participant count
- [ ] List is sorted by date descending (most recent first)
- [ ] Each meeting entry is expandable to show the full transcript
- [ ] Transcript text is formatted with speaker labels and timestamps
- [ ] Pagination or infinite scroll loads additional meetings (20 per page)
- [ ] Last sync timestamp displayed in the gadget header
- [ ] Manual refresh button re-fetches the transcript list
US-002: Search Across Meetings
As a developer I want to search across all meeting transcripts by keyword So that I can find specific discussions about technical topics
Priority: P0
Acceptance Criteria:
- [ ] Search input field in the gadget header with real-time search (debounced 300ms)
- [ ] Search results show matching meetings with highlighted keyword context
- [ ] Each result includes meeting title, date, and the matching transcript excerpt
- [ ] Results are ranked by relevance (most keyword matches first)
- [ ] Cleared search returns to the recent meetings list view
- [ ] Search supports multi-word queries
- [ ] Search history (last 10 queries) stored in localStorage for quick re-search
US-003: Display Meeting Summaries
As a developer I want to see AI-generated meeting summaries So that I can quickly understand meeting outcomes without reading full transcripts
Priority: P1
Acceptance Criteria:
- [ ] Each meeting entry includes a "Summary" tab alongside the "Transcript" tab
- [ ] Summary displays: key topics, action items, decisions made, and follow-ups
- [ ] Summary sections are collapsible for space efficiency
- [ ] Action items are displayed as a checklist (read-only, reflecting Fireflies data)
- [ ] Summary loading shows a skeleton loader while fetching
- [ ] If no summary is available, the tab displays "Summary not yet generated"
US-004: Link Meetings to Sessions and Iterations
As a developer I want to link meeting notes to orchestrata sessions and iterations So that I have complete traceability between meetings and development work
Priority: P1
Acceptance Criteria:
- [ ] Each meeting entry has a "Link to Session" button that opens a session selector
- [ ] Session selector shows recent sessions (from session.list RPC) with number, purpose, and date
- [ ] A meeting can be linked to one or more sessions
- [ ] A meeting can be linked to specific iterations within a session
- [ ] Linked sessions are displayed as tags on the meeting entry
- [ ] The session-manager gadget shows linked meetings in the session detail view (via ctx.bus)
- [ ] Meeting-session links are stored in localStorage and synced via State Sync
- [ ] Removing a link is possible via the meeting entry context menu
US-005: Configure Fireflies Connection
As a developer I want to configure my Fireflies API connection So that the gadget can access my meeting data
Priority: P0
Acceptance Criteria:
- [ ] Settings panel provides an API key input field
- [ ] API key is stored in localStorage encrypted with Web Crypto API (AES-GCM)
- [ ] "Test Connection" button verifies the API key by fetching a single transcript
- [ ] Connection status indicator shows green (connected), yellow (expired), or red (error)
- [ ] Option to choose browser-direct API access or MCP bridge mode
- [ ] MCP bridge URL configurable when bridge mode is selected
- [ ] Clear instructions on how to obtain a Fireflies API key
US-006: MCP Bridge for Server-Side Access
As a system administrator I want a Python-side MCP bridge for Fireflies API access So that the gadget can work in environments where browser-side API calls are restricted by CORS
Priority: P2
Acceptance Criteria:
- [ ] Python MCP bridge exposes Fireflies API methods as gateway-accessible RPC calls
- [ ] Bridge uses the existing Fireflies MCP tools (fireflies_get_transcript, fireflies_search, fireflies_get_summary, fireflies_get_transcripts)
- [ ] Bridge authenticates with Fireflies using server-side API key (not exposed to browser)
- [ ] Gateway RPC methods:
fireflies.transcripts,fireflies.search,fireflies.summary,fireflies.transcript - [ ] Bridge caches transcript data for 10 minutes to reduce API calls
- [ ] Bridge respects Fireflies API rate limits
Standardized Acceptance Criteria
SAC-US001: View Recent Meeting Transcripts
| # | Criterion | Verification |
|---|---|---|
| SAC-US001-01 | Gadget displays a list of recent meetings with title, date, duration, and participant count | DOM query for .fireflies-meeting-entry elements with child .title, .date, .duration, .participants |
| SAC-US001-02 | List is sorted by date descending (most recent first) | Assert data-date attribute of each entry is monotonically decreasing |
| SAC-US001-03 | Each meeting entry is expandable to show the full transcript | Click .meeting-entry → assert .transcript-content visibility toggles |
| SAC-US001-04 | Transcript text is formatted with speaker labels and timestamps | Assert expanded transcript contains .speaker-label and .timestamp elements |
| SAC-US001-05 | Pagination loads additional meetings (20 per page) | Scroll to bottom → assert new API call with offset=20 → assert additional entries appended |
| SAC-US001-06 | Last sync timestamp displayed in the gadget header | Assert .sync-timestamp element displays ISO 8601 formatted time |
| SAC-US001-07 | Manual refresh button re-fetches the transcript list | Click .refresh-btn → assert API call fired → assert list updated |
SAC-US002: Search Across Meetings
| # | Criterion | Verification |
|---|---|---|
| SAC-US002-01 | Search input field in the gadget header with real-time search (debounced 300ms) | Type in .search-input → assert API call fires after 300ms debounce, not before |
| SAC-US002-02 | Search results show matching meetings with highlighted keyword context | Assert .search-result entries contain <mark> elements wrapping the matched keyword |
| SAC-US002-03 | Each result includes meeting title, date, and the matching transcript excerpt | Assert .search-result contains .title, .date, .excerpt child elements |
| SAC-US002-04 | Results are ranked by relevance (most keyword matches first) | Assert data-match-count attribute of results is monotonically decreasing |
| SAC-US002-05 | Cleared search returns to the recent meetings list view | Clear .search-input → assert transcript list view is restored |
| SAC-US002-06 | Search supports multi-word queries | Search "gateway authentication" → assert results returned for multi-word phrase |
| SAC-US002-07 | Search history (last 10 queries) stored in localStorage for quick re-search | After 10 searches → assert localStorage.getItem('commandcenter.state.fireflies.search_history') contains 10 entries |
SAC-US003: Display Meeting Summaries
| # | Criterion | Verification |
|---|---|---|
| SAC-US003-01 | Each meeting entry includes a "Summary" tab alongside the "Transcript" tab | Assert .tab-summary and .tab-transcript elements present per meeting entry |
| SAC-US003-02 | Summary displays: key topics, action items, decisions made, and follow-ups | Assert .summary-topics, .summary-actions, .summary-decisions, .summary-followups sections populated |
| SAC-US003-03 | Summary sections are collapsible for space efficiency | Click section header → assert content visibility toggles via aria-expanded attribute |
| SAC-US003-04 | Action items are displayed as a checklist (read-only, reflecting Fireflies data) | Assert .action-item elements have type="checkbox" with disabled attribute and correct checked state |
| SAC-US003-05 | Summary loading shows a skeleton loader while fetching | Assert .skeleton-loader visible during API call → hidden after response |
| SAC-US003-06 | If no summary is available, the tab displays "Summary not yet generated" | API returns no summary data → assert .no-summary-message with text "Summary not yet generated" |
SAC-US004: Link Meetings to Sessions and Iterations
| # | Criterion | Verification |
|---|---|---|
| SAC-US004-01 | Each meeting entry has a "Link to Session" button that opens a session selector | Assert .link-session-btn present → click → assert .session-selector dialog visible |
| SAC-US004-02 | Session selector shows recent sessions with number, purpose, and date | Assert .session-option entries contain .session-number, .session-purpose, .session-date |
| SAC-US004-03 | A meeting can be linked to one or more sessions | Link meeting to session A and session B → assert both links persisted in localStorage |
| SAC-US004-04 | A meeting can be linked to specific iterations within a session | Select session → select iteration → assert link data includes iteration_number field |
| SAC-US004-05 | Linked sessions are displayed as tags on the meeting entry | After linking → assert .session-tag elements visible on the meeting entry |
| SAC-US004-06 | The session-manager gadget shows linked meetings via ctx.bus | Emit fireflies.meeting.linked → assert session-manager gadget updates its display |
| SAC-US004-07 | Meeting-session links stored in localStorage and synced via State Sync | Assert localStorage.getItem('commandcenter.state.fireflies.session_links') contains link → assert State Sync push called |
| SAC-US004-08 | Removing a link is possible via the meeting entry context menu | Right-click meeting → select "Remove Link" → assert link removed from storage and tags |
SAC-US005: Configure Fireflies Connection
| # | Criterion | Verification |
|---|---|---|
| SAC-US005-01 | Settings panel provides an API key input field | Assert .api-key-input element of type password present in settings panel |
| SAC-US005-02 | API key is stored in localStorage encrypted with Web Crypto API (AES-GCM) | After saving key → assert stored value is base64-encoded ciphertext, not plaintext |
| SAC-US005-03 | "Test Connection" button verifies the API key by fetching a single transcript | Click .test-connection-btn → assert API call to transcripts endpoint with limit=1 |
| SAC-US005-04 | Connection status indicator shows green/yellow/red | After successful test → assert .status-indicator has data-status="connected" with green styling |
| SAC-US005-05 | Option to choose browser-direct API access or MCP bridge mode | Assert .mode-selector radio group with browser_direct and mcp_bridge options |
| SAC-US005-06 | MCP bridge URL configurable when bridge mode is selected | Select mcp_bridge → assert .bridge-url-input becomes visible and editable |
| SAC-US005-07 | Clear instructions on how to obtain a Fireflies API key | Assert .setup-instructions element contains text referencing Fireflies developer portal |
SAC-US006: MCP Bridge for Server-Side Access
| # | Criterion | Verification |
|---|---|---|
| SAC-US006-01 | Python MCP bridge exposes Fireflies API methods as gateway-accessible RPC calls | Send fireflies.transcripts RPC → assert valid response with transcript array |
| SAC-US006-02 | Bridge uses the existing Fireflies MCP tools | Assert bridge implementation delegates to fireflies_get_transcript, fireflies_search, fireflies_get_summary, fireflies_get_transcripts |
| SAC-US006-03 | Bridge authenticates with Fireflies using server-side API key | Assert API key not included in browser-bound RPC responses; assert server-side config contains key |
| SAC-US006-04 | Gateway RPC methods registered under fireflies.* namespace |
Assert gateway method registry contains fireflies.transcripts, fireflies.search, fireflies.summary, fireflies.transcript |
| SAC-US006-05 | Bridge caches transcript data for 10 minutes | Fetch transcript → fetch again within 10 min → assert no upstream API call on second fetch |
| SAC-US006-06 | Bridge respects Fireflies API rate limits | Send 100 rapid requests → assert bridge queues or throttles to stay within rate limit |
Functional Requirements
FR-001: Transcript Listing
User Story: US-001
- System SHALL fetch recent transcripts using the Fireflies REST API
/transcriptsendpoint with pagination parameters - System SHALL display transcript metadata (title, date, duration, participants) in a scrollable list
- System SHALL cache transcript metadata in memory with a configurable TTL (default: 10 minutes)
- System SHALL support expanding a transcript entry to view the full text with speaker labels
- System SHALL handle transcripts with > 100,000 characters by lazy-loading content in chunks
FR-002: Keyword Search
User Story: US-002
- System SHALL submit search queries to the Fireflies REST API
/searchendpoint with the keyword parameter - System SHALL debounce search input by 300ms to prevent excessive API calls
- System SHALL highlight matching keywords in transcript excerpts using
<mark>elements - System SHALL display search results with meeting title, date, and contextual excerpt (100 characters before and after the match)
- System SHALL support pagination of search results (20 results per page)
FR-003: Meeting Summaries
User Story: US-003
- System SHALL fetch meeting summaries from the Fireflies REST API
/summaryendpoint with the transcript ID - System SHALL parse summary response into structured sections: key topics, action items, decisions, follow-ups
- System SHALL cache summaries in memory for the session duration (no TTL expiry while gadget is mounted)
- System SHALL display a "Summary not available" message for meetings where Fireflies has not generated a summary
FR-004: Session Linking
User Story: US-004
- System SHALL store meeting-session links as a JSON array in localStorage under key
commandcenter.state.fireflies.session_links - System SHALL sync meeting-session links to the gateway via State Sync for cross-device persistence
- System SHALL emit
fireflies.meeting.linkedevents onctx.buswhen a meeting is linked to a session - System SHALL listen for
fireflies.meeting.linkedevents and update the display in both the Fireflies gadget and the session-manager gadget - System SHALL support linking meetings to specific iterations by including an optional
iteration_numberin the link data
FR-005: MCP Bridge Integration
User Story: US-006
- System SHALL register a
FirefliesMCPBridgeas a SPEC-015 plugin when server-side access is needed - System SHALL expose Fireflies API methods as gateway RPC methods under the
fireflies.*namespace - System SHALL route gadget API calls through the gateway when MCP bridge mode is enabled in settings
- System SHALL fall back to browser-direct API calls if the MCP bridge is unavailable
- System SHALL cache MCP bridge responses for 10 minutes to reduce upstream API calls
Non-Functional Requirements
Performance
NFR-001: Data Fetching
- Transcript list fetch: < 2s (P95) for 20 transcripts
- Search query response: < 3s (P95)
- Summary fetch: < 2s (P95) per meeting
- Cached data retrieval: < 10ms
NFR-002: Rendering
- Transcript list render with 20 entries: < 100ms
- Full transcript expand (50,000 characters): < 200ms
- Search result highlight render: < 100ms
Reliability
NFR-003: Offline Behavior
- Cached transcripts and summaries remain visible when Fireflies API is unreachable
- Search is unavailable in offline mode (API-dependent)
- Session links persist in localStorage regardless of API availability
NFR-004: Data Integrity
- Meeting-session links are idempotent (linking the same meeting to the same session twice creates only one link)
- Link deletions are propagated to State Sync within the debounce window
Security
NFR-005: Credential Management
- Fireflies API key stored in localStorage encrypted with AES-GCM via Web Crypto API
- API key never transmitted to the Orchestrata gateway (browser-direct mode)
- MCP bridge mode stores API key server-side in gateway configuration
- All Fireflies API calls use HTTPS
NFR-006: Data Privacy
- Meeting transcripts are not stored persistently in the gateway or Neo4j
- Only meeting-session link metadata (meeting ID, session ID) is persisted
- Full transcript data is ephemeral (in-memory cache only)
Technical Design
Architecture
┌──────────────────────────────────────────────────────┐
│ Fireflies Gadget (Browser) │
├──────────────────────────────────────────────────────┤
�� │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ Transcript │ │ Search │ │ Summary │ │
│ │ List View │ │ Panel │ │ Panel │ │
│ └──────────────┘ └──────────────┘ └──���─────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Session │ │ Transcript │ │
│ │ Linker │ │ Cache │ │
│ └──���───────────┘ └──────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────────────────────────────┐ │
│ │ Fireflies API Provider │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Browser- │ │ MCP Bridge │ │ │
│ │ ��� Direct Mode │ │ Mode │ │ │
│ │ │ (REST API) │ │ (via GW RPC) │ │ │
│ │ └──────────────┘ ��──────────────┘ │ │
│ └──────────────────────────────────��─────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ ctx.bus │ │ localStorage │ │
│ │ (session │ │ (API key, │ │
│ │ links) │ │ links, │ │
│ │ │ │ cache) │ │
│ └──────────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────────┐
│ Fireflies.ai │ │ SPEC-014 Gateway │
│ REST API │ │ (MCP Bridge mode) │
│ (api.fireflies │ │ fireflies.* RPC │
│ .ai/graphql) │ │ methods │
└──────────────────┘ └──────────────────────┘
Key Interfaces
/**
* FirefliesGadget — Main gadget class for Fireflies.ai integration.
*/
class FirefliesGadget {
/** Mount the gadget into the Command Center grid. */
async mount(ctx) {}
/** Unmount and clean up subscriptions and cache. */
async unmount() {}
/** Refresh transcript list from API. */
async refresh() {}
/** Search across all transcripts. */
async search(query) {}
}
/**
* IFirefliesProvider — Protocol for Fireflies API access.
*/
class IFirefliesProvider {
/** Fetch list of recent transcripts. */
async getTranscripts(limit, offset) {}
/** Fetch a single transcript by ID. */
async getTranscript(transcriptId) {}
/** Search transcripts by keyword. */
async search(query, limit, offset) {}
/** Fetch AI-generated summary for a transcript. */
async getSummary(transcriptId) {}
/** Test the API connection. */
async testConnection() {}
/** Get provider status. */
getStatus() {}
}
/**
* FirefliesBrowserProvider — Browser-direct Fireflies API access.
*/
class FirefliesBrowserProvider extends IFirefliesProvider {
constructor(apiKey) {}
}
/**
* FirefliesMCPProvider — MCP bridge Fireflies API access via gateway RPC.
*/
class FirefliesMCPProvider extends IFirefliesProvider {
constructor(gadgetBridge) {}
}
/**
* SessionLinker — Manages meeting-to-session/iteration links.
*/
class SessionLinker {
/** Link a meeting to a session. */
async linkToSession(meetingId, sessionId, iterationNumber) {}
/** Remove a meeting-session link. */
async unlinkFromSession(meetingId, sessionId) {}
/** Get all sessions linked to a meeting. */
getLinkedSessions(meetingId) {}
/** Get all meetings linked to a session. */
getLinkedMeetings(sessionId) {}
}
Gadget Manifest
{
"id": "orchestrata-fireflies",
"name": "Fireflies Meetings",
"version": "1.0.0",
"description": "Meeting transcripts, search, and summaries from Fireflies.ai",
"entry": "gadgets/fireflies/fireflies.js",
"icon": "microphone",
"category": "productivity",
"dependencies": ["GadgetBridge"],
"min_api_version": "1.0.0",
"default_size": {"columns": 2, "rows": 2},
"supports_multi_instance": false,
"config_schema": {
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": ["browser_direct", "mcp_bridge"],
"default": "browser_direct"
},
"mcp_bridge_url": {"type": "string"},
"transcripts_per_page": {"type": "integer", "default": 20},
"cache_ttl_minutes": {"type": "integer", "default": 10},
"search_debounce_ms": {"type": "integer", "default": 300}
}
}
}
Meeting-Session Link Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "MeetingSessionLink",
"type": "object",
"required": ["meeting_id", "meeting_title", "session_id"],
"properties": {
"meeting_id": {"type": "string"},
"meeting_title": {"type": "string"},
"meeting_date": {"type": "string", "format": "date-time"},
"session_id": {"type": "string"},
"session_number": {"type": "integer"},
"iteration_number": {
"type": ["integer", "null"],
"description": "Optional specific iteration within the session."
},
"linked_at": {"type": "string", "format": "date-time"},
"linked_by": {"type": "string", "default": "user"}
}
}
MCP Bridge RPC Methods (via SPEC-014 Gateway)
When operating in MCP bridge mode, the following RPC methods are available:
{
"fireflies.transcripts": {
"params": {"limit": 20, "offset": 0},
"result": {"transcripts": [...], "count": 20}
},
"fireflies.transcript": {
"params": {"transcript_id": "abc123"},
"result": {"id": "abc123", "title": "...", "text": "...", "speakers": [...]}
},
"fireflies.search": {
"params": {"query": "gateway authentication", "limit": 20},
"result": {"results": [...], "count": 5}
},
"fireflies.summary": {
"params": {"transcript_id": "abc123"},
"result": {"topics": [...], "action_items": [...], "questions": [...]}
}
}
Configuration
# In configs/command-center.yaml under gadgets section
gadgets:
orchestrata-fireflies:
mode: "browser_direct"
transcripts_per_page: 20
cache_ttl_minutes: 10
search_debounce_ms: 300
# If using MCP bridge mode (in configs/monolithic.yaml)
plugins:
orchestrata-plugin-fireflies-bridge:
api_key: «redacted»
cache_ttl_seconds: 600
rate_limit_rpm: 60
Integration Points
| Component | Integration |
|---|---|
| SPEC-016 VizInt Command Center | Gadget lifecycle, chrome, ctx.bus, GadgetBridge, StateSync |
| Fireflies.ai REST API | Transcript listing, search, summary retrieval |
| Fireflies MCP tools | Server-side API access via MCP bridge |
| SPEC-014 WebSocket Gateway | MCP bridge RPC methods (fireflies.* namespace) |
| SPEC-015 Plugin SDK | MCP bridge plugin registration |
| ctx.bus | Meeting-session link events, session lifecycle awareness |
| localStorage | API key storage, session links, search history, cache |
Success Criteria
- Transcript Display: Recent meeting transcripts displayed within 3 seconds of gadget mount
- Search: Keyword search returns relevant results within 3 seconds with highlighted excerpts
- Summaries: AI-generated meeting summaries displayed with structured sections (topics, actions, decisions)
- Session Linking: Meetings linkable to sessions/iterations with bidirectional visibility
- Dual Mode: Both browser-direct and MCP bridge modes operational
- Offline Resilience: Cached transcripts and summaries visible when API is unreachable
Visual Architecture
Class Diagram
Diagram source shown as text: Mermaid could not parse it (Error: Parse error on line 36:).
classDiagram-direction LR
class CheetahClawsTUI {
+__init__()
#_load_commands(): dict[str, Any]
+async create_checkpoint(name: str): dict[str, Any]
+async rewind(steps: int = 1): dict[str, Any]
+async query_memory(query: str, depth: int = 1): dict[str, Any]
+async edit_file(file_path: str, old_string: str, new_string: str): dict[str, Any]
+async search_files(pattern: str, path: str = '.'): list[str]
+async execute_command(command: str, args: list[str] | None = None): dict[str, Any]
}
class OpenRouterProvider {
+__init__(api_key: str | None = None)
+async chat_completion(model: str, messages: list[dict[str, str]], **kwargs): dict[str, Any]
+get_available_models(): list[str]
+get_model_cost(model: str): float
}
class TodoistIntegration {
+__init__(api_key: str | None = None)
+is_configured(): bool
+async create_project(name: str): str
+async create_task(project_id: str, title: str, **kwargs): str
+async sync_tasks(project_id: str): list[dict[str, Any]]
+async close()
}
class VizIntWebUI {
+__init__(host: str = 'localhost', port: int = 8765)
+async start()
+async shutdown()
+async add_project(project_data: dict[str, Any])
+async broadcast_edit_complete(file_path: str, result: dict[str, Any])
+async update_task_status(task_id: str, status: str)
+async get_projects(): list[dict[str, Any]]
}
FirefliesTranscript Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "FirefliesTranscript",
"type": "object",
"required": ["id", "title", "date", "duration_minutes"],
"properties": {
"id": {"type": "string"},
"title": {"type": "string"},
"date": {"type": "string", "format": "date-time"},
"duration_minutes": {"type": "number"},
"participant_count": {"type": "integer"},
"participants": {
"type": "array",
"items": {"type": "string"}
},
"text": {
"type": "string",
"description": "Full transcript text. May be null in list views (fetched on demand)."
},
"speakers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"segments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"start_time": {"type": "number"},
"end_time": {"type": "number"},
"text": {"type": "string"}
}
}
}
}
}
}
}
}
FirefliesSummary Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "FirefliesSummary",
"type": "object",
"required": ["transcript_id"],
"properties": {
"transcript_id": {"type": "string"},
"topics": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {"type": "string"},
"summary": {"type": "string"}
}
}
},
"action_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"text": {"type": "string"},
"assignee": {"type": "string"},
"completed": {"type": "boolean"}
}
}
},
"questions": {
"type": "array",
"items": {"type": "string"}
},
"follow_ups": {
"type": "array",
"items": {"type": "string"}
}
}
}
FirefliesSearchResult Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "FirefliesSearchResult",
"type": "object",
"required": ["transcript_id", "title", "date", "excerpt"],
"properties": {
"transcript_id": {"type": "string"},
"title": {"type": "string"},
"date": {"type": "string", "format": "date-time"},
"excerpt": {
"type": "string",
"description": "Contextual excerpt with keyword match (100 chars before and after)."
},
"match_count": {"type": "integer"},
"relevance_score": {"type": "number"}
}
}
Error Conditions and Edge Cases
- [ERR-001] If the Fireflies API key is invalid or expired, the gadget SHALL display an "Invalid API Key" error with a link to the settings panel.
- [ERR-002] If the Fireflies API returns a rate limit error (429), the gadget SHALL display a rate limit notice and retry after the
Retry-Afterheader value. - [ERR-003] If a transcript has no speaker labels (audio-only recording without diarization), the gadget SHALL display the text as a single block without speaker attribution.
- [ERR-004] If the MCP bridge is configured but unreachable, the gadget SHALL attempt to fall back to browser-direct mode if an API key is configured locally.
- [ERR-005] If a search query returns zero results, the gadget SHALL display a "No meetings found" message with suggestions (e.g., "Try broader keywords").
- [ERR-006] If a transcript exceeds 100,000 characters, the gadget SHALL lazy-load content in 10,000-character chunks as the user scrolls.
- [ERR-007] If a meeting-session link references a session that no longer exists (deleted or archived), the link SHALL display with a "Session not found" indicator and offer removal.
- [ERR-008] If the Fireflies API is completely unreachable (network error), the gadget SHALL display cached data with a "Last updated: {timestamp}" notice and a retry button.
- [ERR-009] If Web Crypto API is unavailable (non-HTTPS context), the gadget SHALL store the API key in plain text in localStorage and display a security warning.
- [ERR-010] If the summary endpoint returns no summary for a transcript (not yet processed), the gadget SHALL display "Summary generation in progress" and offer manual refresh.
- [ERR-011] If the Fireflies GraphQL API schema changes (field deprecation), the gadget SHALL handle missing fields gracefully with fallback values.
- [ERR-012] If multiple users share the same Orchestrata instance, meeting-session links SHALL be scoped to the authenticated gateway client ID to prevent cross-user link visibility.
Governance
GOV-001: Ownership and Maintenance
Component Owner: Mohamed Technical Lead: Mohamed Maintenance Responsibility: Orchestrata Core Team
The Fireflies Integration specification is owned and maintained by the Orchestrata Core Team. All changes to the specification MUST be reviewed and approved by the technical lead before implementation.
GOV-002: Change Management
Change Approval Process:
- Change proposal submitted via pull request
- Technical review by component owner
- Security review (if applicable)
- Performance impact assessment
- Backward compatibility verification
- Merge upon approval
Breaking Changes:
- Major version increments required for breaking changes
- Migration guide MUST be provided
- Deprecation notice period: 90 days minimum
GOV-003: Compliance and Standards
API Compliance:
- All Fireflies API integrations MUST use HTTPS only
- API keys MUST be encrypted at rest
- No transcript data SHALL be stored persistently in the gateway
- Rate limits MUST be respected (60 RPM default)
Data Governance:
- Meeting transcripts are ephemeral (in-memory only)
- Session links are user-scoped (not shared across users)
- All data retention follows Fireflies.ai data policies
- User consent required for meeting-session linking
Security Governance:
- Annual security audit required
- Credential rotation policy: API keys rotated annually
- Security incident response within 24 hours
- Compliance with Orchestrata security framework (SPEC-099)
GOV-004: Deprecation Policy
Deprecation Triggers:
- Fireflies.ai API deprecation
- Security vulnerabilities in dependencies
- Major architectural changes in Orchestrata
Deprecation Process:
- Minimum 90-day notice period
- Migration guide published
- Alternative solutions documented
- Support continues during notice period
- Final removal with major version increment
GOV-005: Support and SLA
Response Times:
- Critical bugs: 24 hours
- Security issues: 24 hours
- Feature requests: 5 business days
- General questions: 10 business days
Compatibility Guarantee:
- Patch versions: Fully backward compatible
- Minor versions: Backward compatible with deprecation warnings
- Major versions: Breaking changes allowed with migration guide
Performance Requirements
- [PR-001] Transcript list fetch for 20 transcripts SHALL complete within 2 seconds at the 95th percentile.
- [PR-002] Search query response SHALL complete within 3 seconds at the 95th percentile.
- [PR-003] Summary fetch for a single meeting SHALL complete within 2 seconds at the 95th percentile.
- [PR-004] Full transcript display (50,000 characters) SHALL render within 200ms.
- [PR-005] Cached data retrieval SHALL complete within 10ms.
- [PR-006] Search input debounce SHALL prevent more than 3 API calls per second.
- [PR-007] The Fireflies gadget SHALL consume less than 15MB of browser memory with 20 cached transcripts.
- [PR-008] MCP bridge RPC round-trip (browser to gateway to Fireflies API and back) SHALL complete within 4 seconds at the 95th percentile.
Testability Considerations
- [TC-001] The Fireflies API provider SHALL be testable with a real Fireflies API account containing test transcripts in integration tests.
- [TC-002] Search functionality tests SHALL verify keyword highlighting and excerpt extraction with known transcript content.
- [TC-003] Session linker tests SHALL use real localStorage and real ctx.bus events to verify link creation, persistence, and cross-gadget notification.
- [TC-004] MCP bridge tests SHALL use a real SPEC-015 plugin loaded into a real gateway instance and verify RPC call routing.
- [TC-005] Offline resilience tests SHALL disconnect the network (via Playwright) and verify cached data remains visible and API-dependent features are disabled.
- [TC-006] Transcript rendering tests SHALL use real DOM via JSDOM with large transcript payloads to verify lazy-loading and performance.
- [TC-007] Credential encryption tests SHALL verify AES-GCM encryption round-trip using Web Crypto API.
- [TC-008] Fallback mode tests SHALL verify that when MCP bridge is unreachable, the gadget seamlessly switches to browser-direct mode.
Definition of Done
- [DoD-001] All acceptance criteria across all user stories are met and verified with automated tests.
- [DoD-002] Vitest unit test coverage >= 90% for all Fireflies modules (API provider, search, transcript viewer, session linker, cache).
- [DoD-003] Playwright E2E tests pass with a real browser and real Fireflies API (test account).
- [DoD-004] Performance benchmarks meet or exceed all PR-001 through PR-008 thresholds.
- [DoD-005] This specification document is updated to reflect the final implemented design.
- [DoD-006] Fireflies gadget configuration and API key setup instructions are documented.
- [DoD-007] Security review completed covering: API key storage encryption, data privacy (no persistent transcript storage), CORS handling, and HTTPS enforcement.
- [DoD-008] All changes are backward compatible with the stated API version, or migration guidance is provided.
Examples
Example: Fetching Recent Transcripts (Browser-Direct)
const response = await fetch('https://api.fireflies.ai/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
},
body: JSON.stringify({
query: `
query {
transcripts(limit: 20, skip: 0) {
id
title
date
duration
participants
}
}
`,
}),
});
const { data } = await response.json();
// data.transcripts = [{id, title, date, duration, participants}, ...]
Example: Keyword Search
const searchResponse = await fetch('https://api.fireflies.ai/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
},
body: JSON.stringify({
query: `
query SearchTranscripts($keyword: String!) {
transcripts(search: $keyword, limit: 20) {
id
title
date
sentences {
text
speaker_name
}
}
}
`,
variables: { keyword: 'gateway authentication' },
}),
});
Example: Meeting-Session Link
{
"meeting_id": "ff-transcript-abc123",
"meeting_title": "Architecture Review - WebSocket Gateway",
"meeting_date": "2026-03-27T14:00:00Z",
"session_id": "session-089",
"session_number": 89,
"iteration_number": 202,
"linked_at": "2026-03-28T10:30:00Z",
"linked_by": "user"
}
Example: MCP Bridge RPC Call
{
"jsonrpc": "2.0",
"id": "cc-req-042",
"method": "fireflies.search",
"params": {
"query": "plugin sandboxing",
"limit": 20
}
}
Response:
{
"jsonrpc": "2.0",
"id": "cc-req-042",
"result": {
"results": [
{
"transcript_id": "ff-abc123",
"title": "Architecture Review - Plugin System",
"date": "2026-03-25T10:00:00Z",
"excerpt": "...discussed **plugin sandboxing** using Linux namespaces and cgroups...",
"match_count": 3,
"relevance_score": 0.87
}
],
"count": 1
}
}
Example: Summary Display
{
"transcript_id": "ff-abc123",
"topics": [
{
"title": "Plugin Sandboxing Approach",
"summary": "Team decided to use Linux namespaces for filesystem isolation and cgroups for resource limiting."
},
{
"title": "Capability System",
"summary": "Plugins must declare capabilities in manifest. DI container scoped by declared capabilities."
}
],
"action_items": [
{
"text": "Write SPEC-015 Plugin SDK specification",
"assignee": "Mohamed",
"completed": true
},
{
"text": "Prototype capability enforcement in DI container",
"assignee": "Mohamed",
"completed": false
}
],
"questions": [
"Should plugin manifests use YAML format (plugin.yaml)?",
"Can reserved aliases (U:Ox, U:PS, U:KR) be overridden by plugins?"
],
"follow_ups": [
"Review OpenClaw plugin architecture for additional patterns",
"Benchmark plugin hot-reload performance"
]
}
Contracts
Contract: Fireflies Gadget API (contracts/commandcenter/fireflies-v1.0.0.yaml)
info:
title: Fireflies Integration Gadget Contract
version: 1.0.0
spec_id: 018-fireflies-integration
spec_version: 1.0.0
maturity: experimental
consumer: fireflies-gadget
providers: [fireflies-rest-api, fireflies-mcp-bridge]
schemas:
FirefliesTranscript:
type: object
required: [id, title, date, duration_minutes]
properties:
id:
type: string
title:
type: string
date:
type: string
format: date-time
duration_minutes:
type: number
participant_count:
type: integer
participants:
type: array
items:
type: string
text:
type: string
nullable: true
FirefliesSummary:
type: object
required: [transcript_id]
properties:
transcript_id:
type: string
topics:
type: array
items:
type: object
properties:
title:
type: string
summary:
type: string
action_items:
type: array
items:
type: object
properties:
text:
type: string
assignee:
type: string
completed:
type: boolean
questions:
type: array
items:
type: string
follow_ups:
type: array
items:
type: string
FirefliesSearchResult:
type: object
required: [transcript_id, title, date, excerpt]
properties:
transcript_id:
type: string
title:
type: string
date:
type: string
format: date-time
excerpt:
type: string
match_count:
type: integer
relevance_score:
type: number
MeetingSessionLink:
type: object
required: [meeting_id, meeting_title, session_id]
properties:
meeting_id:
type: string
meeting_title:
type: string
meeting_date:
type: string
format: date-time
session_id:
type: string
session_number:
type: integer
iteration_number:
type: integer
nullable: true
linked_at:
type: string
format: date-time
linked_by:
type: string
mcp_bridge_methods:
fireflies.transcripts:
description: Fetch list of recent transcripts
scope_required: read_only
params:
type: object
properties:
limit:
type: integer
default: 20
offset:
type: integer
default: 0
result:
type: object
required: [transcripts, count]
properties:
transcripts:
type: array
items:
$ref: "#/schemas/FirefliesTranscript"
count:
type: integer
description: >
Number of items in THIS page. The Fireflies GraphQL API exposes
no corpus-wide total; a field named "total" here would lie
(2026-07-12 defect fix — page size was being reported as total).
fireflies.transcript:
description: Fetch a single transcript with full text
scope_required: read_only
params:
type: object
required: [transcript_id]
properties:
transcript_id:
type: string
result:
$ref: "#/schemas/FirefliesTranscript"
fireflies.search:
description: Search across transcripts by keyword
scope_required: read_only
params:
type: object
required: [query]
properties:
query:
type: string
limit:
type: integer
default: 20
offset:
type: integer
default: 0
result:
type: object
required: [results, count]
properties:
results:
type: array
items:
$ref: "#/schemas/FirefliesSearchResult"
count:
type: integer
description: Number of results in this page (no corpus total upstream).
fireflies.summary:
description: Fetch AI-generated meeting summary
scope_required: read_only
params:
type: object
required: [transcript_id]
properties:
transcript_id:
type: string
result:
$ref: "#/schemas/FirefliesSummary"
bus_events:
fireflies.meeting.linked:
description: Emitted when a meeting is linked to a session/iteration
payload:
$ref: "#/schemas/MeetingSessionLink"
fireflies.meeting.unlinked:
description: Emitted when a meeting-session link is removed
payload:
type: object
required: [meeting_id, session_id]
properties:
meeting_id:
type: string
session_id:
type: string
performance:
transcript_list_p95_ms: 2000
search_p95_ms: 3000
summary_p95_ms: 2000
transcript_render_p95_ms: 200
cache_hit_ms: 10
mcp_roundtrip_p95_ms: 4000
security:
api_key_storage: localStorage_aes_gcm
transcript_persistence: ephemeral_memory_only
link_data_persistence: localStorage_and_state_sync
api_transport: https_only
spec_traceability:
spec_id: "018-fireflies-integration"
spec_version: "1.0.0"
user_stories: ["US-001", "US-002", "US-003", "US-004", "US-005", "US-006"]
Observability Requirements
OBS-001: Structured Logging
All Fireflies gadget and MCP bridge operations SHALL emit structured log entries.
Browser-Side Logging (Gadget)
| Event | Level | Fields | Destination |
|---|---|---|---|
| Transcript list fetched | INFO | timestamp, transcript_count, fetch_duration_ms, mode (browser/bridge) |
console.log (structured JSON) |
| Transcript expanded | INFO | timestamp, transcript_id, text_length, render_duration_ms |
console.log |
| Search query submitted | INFO | timestamp, query, result_count, search_duration_ms |
console.log |
| Summary fetched | INFO | timestamp, transcript_id, has_topics, has_actions, fetch_duration_ms |
console.log |
| Meeting linked to session | INFO | timestamp, meeting_id, session_id, iteration_number |
console.log |
| API key validation | INFO | timestamp, status (success/failure), mode |
console.log |
| API call failed | ERROR | timestamp, endpoint, status_code, error_message, retry_after_ms |
console.error |
| Cache hit | DEBUG | timestamp, cache_key, cache_age_ms |
console.debug |
| Cache miss | DEBUG | timestamp, cache_key, reason (expired/absent) |
console.debug |
| Fallback to browser-direct | WARNING | timestamp, bridge_url, error_message |
console.warn |
Server-Side Logging (MCP Bridge)
| Event | Level | Fields | Destination |
|---|---|---|---|
| RPC method invoked | INFO | timestamp, method, params, correlation_id, client_id |
Gateway structured log |
| Fireflies API call | INFO | timestamp, endpoint, duration_ms, status_code, correlation_id |
Gateway structured log |
| Fireflies API error | ERROR | timestamp, endpoint, status_code, error_body, correlation_id |
Gateway structured log |
| Rate limit hit | WARNING | timestamp, endpoint, retry_after_s, correlation_id |
Gateway structured log |
| Cache hit (bridge) | DEBUG | timestamp, cache_key, cache_age_s, correlation_id |
Gateway structured log |
| Bridge plugin loaded | INFO | timestamp, plugin_id, version, configured_mode |
Gateway structured log |
| Bridge plugin error | ERROR | timestamp, plugin_id, error_type, error_message, stack_trace |
Gateway structured log |
OBS-002: Metrics
Browser-Side Metrics (Gadget)
Metrics are collected in-memory and exposed via ctx.bus event fireflies.metrics.snapshot for dashboard display.
| Metric | Type | Labels | Description |
|---|---|---|---|
fireflies_api_calls_total |
Counter | endpoint, mode, status |
Total API calls to Fireflies |
fireflies_api_duration_ms |
Histogram | endpoint, mode |
API call duration in milliseconds |
fireflies_cache_hits_total |
Counter | cache_type (transcript/summary/search) |
Total cache hits |
fireflies_cache_misses_total |
Counter | cache_type |
Total cache misses |
fireflies_search_queries_total |
Counter | result_bucket (0, 1-5, 6-20, 20+) |
Total search queries by result count bucket |
fireflies_transcript_renders_total |
Counter | size_bucket (small/medium/large) |
Transcript render events by text size |
fireflies_session_links_total |
Gauge | — | Current number of meeting-session links |
fireflies_errors_total |
Counter | error_type (auth/network/rate_limit/parse) |
Total errors by type |
Server-Side Metrics (MCP Bridge)
Metrics are exposed via the gateway's Prometheus endpoint.
| Metric | Type | Labels | Description |
|---|---|---|---|
fireflies_bridge_rpc_total |
Counter | method, status |
Total RPC calls handled by the bridge |
fireflies_bridge_rpc_duration_seconds |
Histogram | method |
RPC call duration including upstream API time |
fireflies_bridge_upstream_calls_total |
Counter | endpoint, status_code |
Total calls to Fireflies upstream API |
fireflies_bridge_upstream_duration_seconds |
Histogram | endpoint |
Upstream API call duration |
fireflies_bridge_cache_size_bytes |
Gauge | — | Current size of the bridge transcript cache |
fireflies_bridge_cache_entries |
Gauge | cache_type |
Number of cached entries by type |
fireflies_bridge_rate_limit_throttles_total |
Counter | endpoint |
Times the bridge throttled due to rate limits |
OBS-003: Distributed Tracing
- Each gadget API call SHALL generate a unique
correlation_id(UUID v4) included in all log entries for that call chain. - When using MCP bridge mode, the
correlation_idSHALL be passed as a parameter in the RPC call and propagated to all upstream Fireflies API requests. - MCP bridge SHALL create trace spans for each RPC method invocation with the following structure:
| Span Name | Parent | Attributes |
|---|---|---|
fireflies.rpc.{method} |
Gateway request span | rpc.method, client_id, correlation_id |
fireflies.upstream.{endpoint} |
fireflies.rpc.{method} |
http.url, http.method, http.status_code, duration_ms |
fireflies.cache.lookup |
fireflies.rpc.{method} |
cache.hit, cache.key, cache.age_ms |
- Trace context SHALL follow the W3C Trace Context format (
traceparentheader) for upstream Fireflies API calls when supported.
OBS-004: Health Checks
Browser-Side Health (Gadget)
The gadget SHALL expose its health status via ctx.bus event fireflies.health and display it in the gadget chrome status indicator.
{
"status": "healthy",
"components": {
"api_connection": {
"status": "healthy",
"mode": "browser_direct",
"last_successful_call": "2026-03-28T14:30:00Z",
"latency_ms": 850
},
"cache": {
"status": "healthy",
"entries": 20,
"oldest_entry_age_ms": 540000
},
"local_storage": {
"status": "healthy",
"links_count": 5,
"api_key_configured": true
}
},
"uptime_ms": 3600000
}
Health status mapping:
- healthy: API reachable, cache populated, API key configured
- degraded: API unreachable but cached data available, or API key missing but bridge mode configured
- unhealthy: No API access and no cached data, or localStorage unavailable
Server-Side Health (MCP Bridge)
The MCP bridge plugin SHALL report health via the gateway's plugin health system.
{
"status": "healthy",
"components": {
"fireflies_api": {
"status": "healthy",
"last_successful_call": "2026-03-28T14:30:00Z",
"latency_ms": 420
},
"cache": {
"status": "healthy",
"entries": 45,
"size_bytes": 2340000,
"hit_rate_percent": 73.2
},
"rate_limiter": {
"status": "healthy",
"remaining_calls": 42,
"reset_at": "2026-03-28T14:31:00Z"
}
},
"uptime_seconds": 86400
}
Health check polling interval: 60 seconds (configurable via health_check_interval_s in plugin config).
API Contracts
REST API Endpoints
# Example endpoint definition
GET /api/v1/resource/{id}
Response (200):
type: object
required:
- id
- name
properties:
id: { type: string }
name: { type: string }
Response (404):
$ref: '#/components/schemas/ErrorResponse'
Error Response Schema
components:
schemas:
ErrorResponse:
type: object
required:
- error
- message
- timestamp
properties:
error: { type: string }
message: { type: string }
timestamp: { type: string, format: date-time }
request_id: { type: string }
trace_id: { type: string }
details: { type: array, items: { type: object } }
API Versioning
All APIs use path-based versioning (/api/v1/). Breaking changes require increment to v2.
Revision History
| Date | Version | Author | Changes |
|---|---|---|---|
| 2026-03-28 | 1.0.0 | Mohamed | Initial specification |