Skip to main content

Architecture Decision Records (ADRs)

This directory contains Architecture Decision Records documenting significant technical decisions made in the Teams for Linux project.

What are ADRs?​

Architecture Decision Records capture important architectural decisions along with their context and consequences. They help:

  • Document the "why" behind technical choices
  • Preserve context for future maintainers
  • Enable better decisions by learning from past choices
  • Onboard contributors faster by explaining rationale

Status Overview​

ADRTitleStatusDateVersion
001DesktopCapturer Source ID Format✅ Implemented2025-09-15v2.3.0+
002Token Cache Secure Storage✅ Implemented2025-09-08v2.5.9
003Token Refresh Implementation✅ Implemented2025-09-22v2.6.0
004agents.md Standard Investigation❌ Rejected2025-11-16N/A
005AI-Powered Changelog Generation🔄 Superseded by 0232025-11-17v2.6.15
006CLI Argument Parsing Library✅ Implemented2025-11-19N/A
007Embedded MQTT Broker❌ Rejected2025-11-19N/A
008useSystemPicker Feature for Electron 38❌ Rejected2025-11-24N/A
009Automated Testing Strategy✅ Implemented2025-12-13v2.7.4+
010Multiple Windows Support🔄 Superseded by 0322025-11-26N/A
011AppImage Update Info for Third-Party Managers🔄 Superseded2026-01-25v2.7.1
012Intune SSO Broker Compatibility✅ Implemented2026-01-25v2.7.1
013PII Log Sanitization✅ Implemented2026-01-31v2.7.3
014Quick Chat Deep Link Approach✅ Implemented2026-01-31v2.7.3
015Quick Chat Inline Messaging✅ Implemented2026-02-04N/A
016Cross-Distro Testing Environment✅ Implemented2026-02-25v2.7.9
017Use workflow_run for PR Artifact Comments✅ Implemented2026-02-26N/A
018Issue Triage Bot GitHub App Migration✅ Implemented2026-03-06N/A
019Repository Activity Dashboard✅ Implemented2026-03-11N/A
020Multi-Account Profile Switcher✅ Implemented2026-04-16v2.9.0+
021WebAuthn / FIDO2 Hardware Security Keys on Linux✅ Implemented2026-04-21v2.10.0
022Custom Notification Toast Scope✅ Implemented2025-11-16v2.6.16
023Release Automation Tooling✅ Implemented2026-03-13N/A
024Smartcard PKCS#11 PIN Dialog✅ Implemented2026-06-09v2.14.0
025Configuration Option Naming Convention✅ Accepted2026-08-11N/A
026Performance Audit Outcomes✅ Accepted2026-08-11N/A
028One-Time-Code Pre-fill on Third-Party IdPs❌ Rejected2026-08-19N/A
029Configuration Schema as Single Source of Truth✅ Accepted2026-09-05v2.12.0+
030Graph API Access via the Teams Session Token✅ Implemented2025-11-21v2.6.17
031Keep the --ozone-platform=x11 Default on Wayland✅ Accepted2026-09-05N/A
032Opt-in Secondary Window for the Same Account During Calls🚧 Proposed2026-09-18N/A

Legend:

  • ✅ Implemented - Decision accepted and code in production
  • ✅ Accepted - Decision accepted, implementation pending or partial
  • ❌ Rejected - Decision evaluated and declined with rationale
  • 🚧 Proposed - Under review, not yet accepted
  • 🔄 Superseded - Replaced by a newer decision

By Topic​

Authentication & Security​

ADRTitleSummary
002Token Cache Secure StorageSecure token storage using Electron safeStorage with OS-level encryption to prevent daily re-authentication
003Token Refresh ImplementationConfigurable token refresh mechanism to proactively renew authentication before expiry
012Intune SSO Broker CompatibilityDirect D-Bus invocation for Microsoft Identity Broker version compatibility
013PII Log SanitizationCustom regex sanitizer to redact sensitive data from logs
021WebAuthn / FIDO2 Hardware Security KeysFIDO2 hardware key support on Linux via fido2-tools interception
024Smartcard PKCS#11 PIN DialogPIN collected in a hardened main-process window, never injected into the Teams page
028One-Time-Code Pre-fill on Third-Party IdPsRejected DOM-based OTC pre-fill for Okta and similar; Electron cannot host a password-manager extension, so contract-backed factors are the answer
030Graph API Access via the Teams Session TokenReuse the Teams web app's own Graph token for API access instead of registering a separate Azure AD application

Key Outcomes:

  • Eliminated daily re-authentication issues
  • Platform-native secure storage (Keychain/DPAPI/kwallet)
  • Graceful fallback for unsupported platforms
  • Configurable refresh intervals
  • Support for Microsoft Identity Broker versions ≤ 2.0.1 and > 2.0.1
  • PII sanitization with zero dependencies, UUIDs correlatable for debugging
  • Graph API token reuse needs no app registration or admin consent, but caps scopes at what Teams web already holds (/me/presence returns 403)

Screen Sharing​

ADRTitleSummary
001DesktopCapturer Source ID FormatUse screen:x:y format throughout screen sharing pipeline for Wayland compatibility
008useSystemPicker Feature for Electron 38Rejected OS native picker due to incomplete Linux Wayland/PipeWire support

Key Outcomes:

  • Fixed Wayland screen sharing preview
  • Standardized source identification
  • Improved cross-platform compatibility
  • Deferred native picker until Linux support available

Linux Desktop & Display Server​

ADRTitleSummary
031Keep the --ozone-platform=x11 Default on WaylandShip --ozone-platform=x11 as the default on deb, rpm, AppImage and snap; #2506 was reverted the same day as an accidental merge, and #2601 was closed unmerged after a regression, with concrete reopen triggers recorded

Key Outcomes:

  • Predictable default rendering path across deb, rpm, AppImage, tar.gz and snap
  • electronCLIFlags cannot override the flag; only a genuine command-line or .desktop override can
  • Reopen triggers tied to a working snap core24 migration, a verified Electron/Chromium fix, and ADR-016 matrix validation

Testing & Quality​

ADRTitleSummary
009Automated Testing StrategySmoke testing with Playwright; comprehensive testing impractical due to MS authentication constraints
016Cross-Distro Testing EnvironmentDocker-based manual testing across 9 distro/display server combinations via noVNC, hosted on GitHub Codespaces

Key Outcomes:

  • Playwright E2E smoke tests validate app launch and login redirect
  • Tests run in isolated temp directories for clean state
  • Manual testing remains primary quality gate for feature changes
  • Low maintenance approach suitable for volunteer-maintained project
  • 9 cross-distro configurations testable from a browser via Codespaces
  • Apple Silicon limitation documented (V8 4GB heap cap under Rosetta 2)

Performance​

ADRTitleSummary
026Performance Audit OutcomesCloses the system performance research: outcomes for all ten findings, timeout-budget offline detection, no instrumentation module

Key Outcomes:

  • All ten audit findings closed with explicit outcomes and reopen triggers
  • Offline detection bounded by a 20 s budget that assumes online on exhaustion
  • MutationObserver consolidation rejected; scope-narrowing and polling reduction reserved as first levers
  • No performance instrumentation, deliberately

Documentation & Standards​

ADRTitleSummary
004agents.md Standard InvestigationInvestigated and rejected agents.md standard in favor of tool-specific standards (CLAUDE.md, copilot-instructions.md)
025Configuration Option Naming ConventionNesting criteria, positive naming, and the resolved flat-to-nested rename mapping for configuration options
029Configuration Schema as Single Source of TruthOne-schema-three-consumers thesis: app/config/options.js feeds the generated docs, the docs explorer, and startup validation

Key Outcomes:

  • Consolidated instruction files (removed 28% duplication)
  • Centralized markdown standards in contributing.md
  • Maintained tool-specific official standards
  • Configuration option naming convention and rename mapping owned by ADR-025
  • Configuration schema treated as single source of truth for generated docs, the docs explorer, and startup validation, owned by ADR-029

Release Process & Automation​

ADRTitleSummary
005AI-Powered Changelog GenerationUse Gemini 2.0 Flash for automated changelog generation with release-pr workflow
017Use workflow_run for PR Artifact CommentsMove PR artifact commenting to a workflow_run-triggered workflow to support fork PRs
018Issue Triage Bot GitHub App MigrationMigrate triage bot from in-repo GitHub Actions to standalone Go service as a GitHub App
023Release Automation ToolingAdopt release-please for conventional-commit driven versioning, rejecting release-it and Beads

Key Outcomes:

  • Decoupled merging from releasing
  • AI-generated concise changelog entries (60 chars avg vs 165 manual)
  • Quality score: 9.0/10 on validation testing
  • Zero cost (uses Gemini API free tier)
  • Fork PRs receive artifact download comments without 403 permission errors
  • Issue triage bot runs as a standalone GitHub App with one-click installation and no in-repo workflow files

Community & Metrics​

ADRTitleSummary
019Repository Activity DashboardUse Repobeats for embeddable repo activity visualization in README and docs

Key Outcomes:

  • Repobeats SVG embed added to project README for at-a-glance activity stats
  • Zero maintenance: hosted service updates automatically
  • No CI/CD cost or GitHub Actions minutes consumed

MQTT & Integration​

ADRTitleSummary
006CLI Argument Parsing LibraryKeep yargs for config parsing, use MQTT for action commands instead of CLI subcommands
007Embedded MQTT BrokerRejected bundling Aedes broker - users still need client tools, better alternatives exist

Key Outcomes:

  • Avoid fragile CLI argument bypass layer
  • MQTT commands provide clean architecture for external triggers
  • Users provide own MQTT broker (localhost or Home Assistant)
  • Consider HTTP server for zero-dependency alternative (future)

UI Features​

ADRTitleSummary
010Multiple Windows SupportRejected multi-window in 2025; superseded by 032 after the web app was shown to allow concurrent instances
032Opt-in Secondary Window for the Same Account During CallsOpt-in second BrowserWindow on the same partition so a call can live in one window while the other stays a full client; meeting links and a calendar-based join route to it, no DOM hooks, the call itself is never moved
014Quick Chat Deep Link ApproachUse People API + Deep Links for quick chat access after Chat API was blocked
015Quick Chat Inline MessagingHybrid Teams commanding + Graph API approach for inline message sending
020Multi-Account Profile SwitcherWebContentsView-based profile switching with feature-flag gating
022Custom Notification Toast ScopeKeep the opt-in custom toast, drop the Phase 2 notification centre as unverifiable

Key Outcomes:

  • Quick chat access via People API (works) instead of Chat API (blocked 403)
  • Inline message sending via Graph API ChatMessage.Send scope
  • Chat resolution via Teams entityCommanding + DOM scanning + member verification
  • Keyboard shortcut toggles quick chat modal
  • Multi-account profile switcher shipped Phase 1 from v2.9.0; Phase 2 in progress

Distribution & Packaging​

ADRTitleSummary
011AppImage Update InfoPost-process AppImages with appimagetool to embed update info for third-party update managers

Key Outcomes:

  • Third-party tools (Gear Lever, AppImageUpdate) can detect and manage updates
  • Delta updates via .zsync files reduce bandwidth
  • Both electron-updater and AppImage update info coexist
  • Adds ~2-3 minutes to CI build time

Creating New ADRs​

When to Create an ADR​

Create an ADR for decisions that:

  • Have significant architectural impact
  • Affect multiple modules or systems
  • Involve trade-offs between alternatives
  • Need to be explained to future contributors
  • Change existing patterns or conventions

ADR Template​

Use this template for new ADRs (save as docs-site/docs/development/adr/00X-your-title.md):

---
id: 00X-your-title
---

# ADR 00X: [Title - Short Noun Phrase]

## Status

[Proposed | Accepted | Implemented | Rejected | Superseded by ADR-XXX]

## Context

What is the issue we're trying to address? Include:
- Problem description
- Why this needs a decision now
- Technical background and constraints
- What we investigated or researched

## Decision

What did we decide to do? Be specific:
- Exact approach chosen
- Implementation strategy
- Key parameters or configurations

## Consequences

What are the impacts of this decision?

### Positive
- Benefits gained
- Problems solved
- Improvements delivered

### Negative
- Trade-offs accepted
- Limitations introduced
- Future constraints

### Neutral
- Implementation notes
- Maintenance considerations
- Migration requirements (if applicable)

## Alternatives Considered

What other options did we evaluate and why were they not chosen?

### Option 1: [Name]
- Description
- Pros
- Cons
- **Why rejected**: [Specific reason]

### Option 2: [Name]
- ...

## Related
- ADR-XXX: [Related decision]
- Issue #XXX
- PR #XXX

ADR Naming Conventions​

  • Number: Sequential (001, 002, 003, ...)
  • Title: Short, descriptive noun phrase
  • Filename: 00X-lowercase-with-hyphens.md

Examples:

  • ✅ 001-desktopcapturer-source-id-format.md
  • ✅ 002-token-cache-secure-storage.md
  • ❌ 001-screen-sharing-bug-fix.md (too vague)
  • ❌ 001-ImplementDesktopCapturerFix.md (wrong case)

ADR Workflow​

  1. Create draft ADR with "Proposed" status
  2. Discuss with maintainers (GitHub discussion or PR)
  3. Update status to "Accepted" or "Rejected" based on outcome
  4. Implement (if accepted)
  5. Update status to "Implemented" when deployed
  6. Add to this index in the appropriate topic category

ADR Maintenance​

Updating Existing ADRs​

  • Status changes: Update when implementation completes or decision is superseded
  • Consequences: Add learned lessons or unexpected outcomes after implementation
  • Version notes: Add when decision affects specific releases

Superseding ADRs​

When replacing an old decision:

  1. Create new ADR documenting the new approach
  2. Update old ADR status to: Superseded by ADR-XXX
  3. Link new ADR to old one in "Related" section
  4. Explain in new ADR why the old approach was replaced

Example Supersession​

## Status

~~Accepted~~ → Superseded by [ADR-008](008-new-approach.md)

**Note**: This approach was replaced in November 2025 due to [reason].
See ADR-008 for the current implementation.

Best Practices​

Writing Good ADRs​

✅ Do:

  • Write for future readers who don't have your context
  • Explain the "why" more than the "what"
  • Document alternatives considered
  • Include specific examples and code references
  • Update ADR when you learn something new post-implementation

❌ Don't:

  • Write implementation documentation (that belongs in module READMEs)
  • Skip the consequences section
  • Forget to add links to related issues/PRs
  • Leave status outdated (update when implemented)

ADR Size Guidelines​

  • Minimum: ~200 words (if shorter, might not need an ADR)
  • Typical: 500-1000 words
  • Maximum: No hard limit, but consider splitting if >2000 words

Code References​

When referencing code in ADRs:

**Implementation**: `app/browser/tools/tokenCache.js`
**Configuration**: See `config.json` → `tokenRefreshInterval`
**IPC Channel**: `token-refresh:trigger`

ADR Statistics​

  • Total ADRs: 31
  • Implemented: 19
  • Accepted: 4
  • Proposed: 1
  • Rejected: 4
  • Superseded: 3
  • Average length: ~1050 words
  • Topics covered: 11 (Authentication & Security, Screen Sharing, Linux Desktop & Display Server, Testing & Quality, Performance, Documentation & Standards, Release Process & Automation, Community & Metrics, MQTT & Integration, UI Features, Distribution & Packaging)

Questions?​

  • "Should I create an ADR for this?" → If you're asking, probably yes. When in doubt, create one.
  • "Where do implementation details go?" → Module READMEs. ADRs explain "why", READMEs explain "how".
  • "Can I update an old ADR?" → Yes! Add consequences learned or update status. Don't rewrite history, but do add learnings.
  • "What if my decision was wrong?" → Document it! Create a new ADR explaining why you're changing course. This is valuable learning.

External Resources​