- Consolidated documentation from Ralph Loop iterations - Archived 20+ outdated/superseded files to .archive/ - Kept essential docs: OIDC integration, mobile setup, quick start - Added operational scripts for health monitoring and backup - Research artifacts preserved in .tasks/artifacts/ Current state: - 3 VPS sites (fry, proton, photon) ONLINE in Pangolin - brn-home site pending for local services (Jellyfin, etc.) - Mobile access configuration pending Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
620 lines
18 KiB
Markdown
620 lines
18 KiB
Markdown
# Jellyfin SSO-Auth Plugin Configuration for Authentik OIDC
|
|
|
|
**Research Date:** 2026-01-20
|
|
**Plugin:** jellyfin-plugin-sso by 9p4
|
|
**Target IDP:** Authentik OIDC
|
|
**Documentation Version:** Based on plugin v3.5+ and Jellyfin 10.9+
|
|
|
|
---
|
|
|
|
## Executive Summary
|
|
|
|
The Jellyfin SSO-Auth plugin enables OpenID Connect (OIDC) authentication with Authentik, allowing users to authenticate via SSO. This document covers installation, claim mapping configuration, and critical mobile app authentication workflows.
|
|
|
|
**Key Findings:**
|
|
- Plugin supports OIDC providers including Authentik, Authelia, Keycloak, and others
|
|
- Claim mapping is essential for role-based authorization
|
|
- Mobile apps have SSO limitations requiring alternative authentication methods
|
|
- Quick Connect and API tokens are recommended for mobile app access
|
|
|
|
---
|
|
|
|
## 1. Plugin Installation Process
|
|
|
|
### 1.1 Installation via Web GUI
|
|
|
|
1. **Access Jellyfin Administration Dashboard**
|
|
- Navigate to your Jellyfin instance (e.g., `https://jellyfin.example.com`)
|
|
- Log in with administrator credentials
|
|
- Go to **Dashboard** → **Plugins**
|
|
|
|
2. **Add Plugin Repository**
|
|
- Click on the **Repositories** tab
|
|
- Click the **+** button to add a new repository
|
|
- Enter the following details:
|
|
- **Repository Name:** `Jellyfin SSO`
|
|
- **Repository URL:** `https://raw.githubusercontent.com/9p4/jellyfin-plugin-sso/manifest-release/manifest.json`
|
|
- Click **Save**
|
|
- Confirm the repository installation
|
|
|
|
3. **Install SSO-Auth Plugin**
|
|
- Go to the **Catalog** tab
|
|
- Find **SSO Authentication** in the **Authentication** section
|
|
- Click **Install**
|
|
- Confirm the plugin installation
|
|
- **Restart Jellyfin** for the plugin to activate
|
|
|
|
### 1.2 Configuration File Location
|
|
|
|
After installation, the plugin configuration is stored at:
|
|
```
|
|
/config/data/plugins/configurations/SSO-Auth.xml
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Authentik OIDC Provider Configuration
|
|
|
|
### 2.1 Authentik Setup
|
|
|
|
In Authentik, create an OIDC provider with the following settings:
|
|
|
|
**Provider Settings:**
|
|
- **Name:** `Jellyfin`
|
|
- **Client Type:** `Confidential`
|
|
- **Client ID:** `jellyfin` (or custom value)
|
|
- **Client Secret:** Generate secure secret
|
|
- **Redirect URIs:**
|
|
```
|
|
https://jellyfin.example.com/sso/OID/redirect/authentik
|
|
```
|
|
- **Token Endpoint Auth Method:** `client_secret_post` (CRITICAL for compatibility)
|
|
- **Scopes:** `openid`, `profile`, `email`, `groups`
|
|
|
|
**Important Note:** The plugin uses `client_secret_post` authentication method. Ensure Authentik is configured to accept this method. Mismatch causes authentication failures:
|
|
|
|
```
|
|
Client authentication failed... The registered client with id 'jellyfin' is configured
|
|
to only support 'token_endpoint_auth_method' method 'client_secret_basic'.
|
|
```
|
|
|
|
### 2.2 Authentik Group Configuration
|
|
|
|
Create groups for role-based access:
|
|
- **jellyfin-admins** - Administrative access
|
|
- **jellyfin-users** - Standard user access
|
|
|
|
Assign users to appropriate groups in Authentik.
|
|
|
|
### 2.3 Authentik Scope and Property Mappings
|
|
|
|
Ensure the following claim mappings are configured:
|
|
- **preferred_username** - Username claim
|
|
- **email** - Email address
|
|
- **groups** - User group memberships (CRITICAL for role authorization)
|
|
|
|
---
|
|
|
|
## 3. Jellyfin SSO Plugin Configuration
|
|
|
|
### 3.1 Configuration via Web GUI
|
|
|
|
1. **Navigate to Plugin Settings**
|
|
- Dashboard → **Plugins** → **SSO-Auth**
|
|
|
|
2. **Add OIDC Provider**
|
|
- Click **Add Provider**
|
|
- Configure the following settings:
|
|
|
|
**Basic Configuration:**
|
|
```
|
|
Name of OID Provider: authentik
|
|
OID Endpoint: https://auth.example.com
|
|
OpenID Client ID: jellyfin
|
|
OID Secret: <your-secure-secret>
|
|
```
|
|
|
|
**Authorization Settings:**
|
|
```
|
|
Enabled: ☑ (checked)
|
|
Enable Authorization by Plugin: ☑ (checked)
|
|
Enable All Folders: ☑ (checked)
|
|
```
|
|
|
|
**Role Mapping:**
|
|
```
|
|
Roles: jellyfin-users, jellyfin-admins
|
|
Admin Roles: jellyfin-admins
|
|
Role Claim: groups
|
|
```
|
|
|
|
**Advanced Settings:**
|
|
```
|
|
Request Additional Scopes: groups
|
|
Default Username Claim: preferred_username
|
|
New Path (recommended): ☑ (checked)
|
|
Disable HTTPS: ☐ (unchecked)
|
|
Do Not Validate Endpoints: ☐ (unchecked)
|
|
Do Not Validate Issuer Name: ☐ (unchecked)
|
|
```
|
|
|
|
3. **Save Configuration**
|
|
- Click **Save**
|
|
- The plugin is now active
|
|
|
|
### 3.2 Configuration via XML File
|
|
|
|
Alternatively, configure via the XML file at `/config/data/plugins/configurations/SSO-Auth.xml`:
|
|
|
|
```xml
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<PluginConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
|
<SamlConfigs />
|
|
<OidConfigs>
|
|
<item>
|
|
<key>
|
|
<string>authentik</string>
|
|
</key>
|
|
<value>
|
|
<PluginConfiguration>
|
|
<OidEndpoint>https://auth.example.com</OidEndpoint>
|
|
<OidClientId>jellyfin</OidClientId>
|
|
<OidSecret>your-secure-secret</OidSecret>
|
|
<Enabled>true</Enabled>
|
|
<EnableAuthorization>true</EnableAuthorization>
|
|
<EnableAllFolders>true</EnableAllFolders>
|
|
<EnabledFolders />
|
|
<AdminRoles>
|
|
<string>jellyfin-admins</string>
|
|
</AdminRoles>
|
|
<Roles>
|
|
<string>jellyfin-users</string>
|
|
<string>jellyfin-admins</string>
|
|
</Roles>
|
|
<EnableFolderRoles>false</EnableFolderRoles>
|
|
<EnableLiveTvRoles>false</EnableLiveTvRoles>
|
|
<EnableLiveTv>false</EnableLiveTv>
|
|
<EnableLiveTvManagement>false</EnableLiveTvManagement>
|
|
<LiveTvRoles />
|
|
<LiveTvManagementRoles />
|
|
<FolderRoleMappings />
|
|
<RoleClaim>groups</RoleClaim>
|
|
<OidScopes>
|
|
<string>groups</string>
|
|
</OidScopes>
|
|
<DefaultUsernameClaim>preferred_username</DefaultUsernameClaim>
|
|
<NewPath>true</NewPath>
|
|
<CanonicalLinks />
|
|
<DisableHttps>false</DisableHttps>
|
|
<DisablePushedAuthorization>false</DisablePushedAuthorization>
|
|
<DoNotValidateEndpoints>false</DoNotValidateEndpoints>
|
|
<DoNotValidateIssuerName>false</DoNotValidateIssuerName>
|
|
</PluginConfiguration>
|
|
</value>
|
|
</item>
|
|
</OidConfigs>
|
|
</PluginConfiguration>
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Claim Mapping Configuration
|
|
|
|
### 4.1 Understanding Role Claims
|
|
|
|
The plugin uses the `RoleClaim` setting to determine which OIDC claim contains user roles. Common patterns:
|
|
|
|
**Standard Groups Claim:**
|
|
```xml
|
|
<RoleClaim>groups</RoleClaim>
|
|
```
|
|
|
|
**Nested Claims (e.g., Keycloak):**
|
|
```xml
|
|
<RoleClaim>realm_access.roles</RoleClaim>
|
|
```
|
|
|
|
**Complex Nested Claims:**
|
|
```xml
|
|
<RoleClaim>resource_access.jellyfin.roles</RoleClaim>
|
|
```
|
|
|
|
### 4.2 Common Claim Mapping Issues
|
|
|
|
**Issue: Incorrect role claims warning**
|
|
```
|
|
OpenID user "username" has one or more incorrect role claims:
|
|
[{"Type": "groups", "Value": "jellyfin-admin"}]. Expected any one of: ["jellyfin-admins"]
|
|
```
|
|
|
|
**Solution:** Ensure exact match between:
|
|
1. Group names in Authentik
|
|
2. Role values in plugin configuration (`<AdminRoles>`, `<Roles>`)
|
|
3. Case sensitivity matters
|
|
|
|
### 4.3 Username Claim Mapping
|
|
|
|
The plugin supports multiple username claim sources:
|
|
|
|
```xml
|
|
<DefaultUsernameClaim>preferred_username</DefaultUsernameClaim>
|
|
```
|
|
|
|
**Supported Claims:**
|
|
- `preferred_username` - Most common
|
|
- `email` - Email address as username
|
|
- `sub` - OIDC subject identifier
|
|
- `name` - Display name
|
|
|
|
### 4.4 Additional Scopes
|
|
|
|
Request additional claims beyond the default `openid` scope:
|
|
|
|
```xml
|
|
<OidScopes>
|
|
<string>groups</string>
|
|
<string>email</string>
|
|
<string>profile</string>
|
|
</OidScopes>
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Mobile App Authentication Workflow
|
|
|
|
### 5.1 The Mobile App SSO Problem
|
|
|
|
**Critical Finding:** Jellyfin mobile apps (Android/iOS) have limited SSO support. When using SSO login on mobile:
|
|
|
|
**Observed Behavior:**
|
|
- User clicks "Sign in with SSO"
|
|
- Browser-based authentication completes successfully
|
|
- Redirect returns to app
|
|
- App hangs on "Logging in..." indefinitely
|
|
- Session is not established
|
|
|
|
**Root Cause:**
|
|
- Mobile apps expect traditional username/password authentication
|
|
- Web-based OIDC flow completes but token is not properly transferred to app
|
|
- Issue documented in plugin Issue #189 (Jellyfin 10.9+)
|
|
|
|
### 5.2 Recommended Mobile App Solutions
|
|
|
|
#### Option 1: Quick Connect (Recommended)
|
|
|
|
Quick Connect allows mobile apps to authenticate without entering credentials:
|
|
|
|
**How It Works:**
|
|
1. User opens Jellyfin mobile app
|
|
2. App displays a 6-digit code
|
|
3. User logs into web interface (via SSO)
|
|
4. User enters the 6-digit code in web dashboard
|
|
5. Mobile app is authorized automatically
|
|
|
|
**Configuration:**
|
|
- Enable Quick Connect in Jellyfin Dashboard
|
|
- Dashboard → **Networking** → **Quick Connect**
|
|
- Check "Enable Quick Connect"
|
|
|
|
**Usage:**
|
|
1. Mobile app: **Settings** → **Add Server** → **Quick Connect**
|
|
2. Note the 6-digit code
|
|
3. Web browser: Login via SSO → **Dashboard** → **Quick Connect**
|
|
4. Enter code and authorize
|
|
5. Mobile app connects automatically
|
|
|
|
#### Option 2: API Token Authentication
|
|
|
|
Generate an API token for mobile app access:
|
|
|
|
**Steps:**
|
|
1. Login to Jellyfin web interface via SSO
|
|
2. Navigate to **Dashboard** → **API Keys**
|
|
3. Click **+** to create new API key
|
|
4. Name: "Mobile App - [Device Name]"
|
|
5. Copy the generated API token
|
|
6. In mobile app: Use token instead of password
|
|
|
|
**Security Considerations:**
|
|
- Tokens should be device-specific
|
|
- Revoke tokens for lost/stolen devices
|
|
- Rotate tokens periodically
|
|
- Monitor active sessions in Dashboard
|
|
|
|
#### Option 3: Fallback Local Authentication
|
|
|
|
Configure the plugin to allow fallback to local Jellyfin authentication:
|
|
|
|
```xml
|
|
<DefaultProvider>Jellyfin.Server.Implementations.Users.DefaultAuthenticationProvider</DefaultProvider>
|
|
```
|
|
|
|
**Workflow:**
|
|
- Web users: Use SSO
|
|
- Mobile users: Use Jellyfin username/password
|
|
- Maintain separate password for mobile access
|
|
- Less secure but functional
|
|
|
|
### 5.3 Mobile App Compatibility Matrix
|
|
|
|
| App | SSO Support | Quick Connect | API Token | Notes |
|
|
|-----|-------------|---------------|-----------|-------|
|
|
| Jellyfin Android | Partial | ✓ | ✓ | SSO hangs on "Logging in" |
|
|
| Jellyfin iOS | Partial | ✓ | ✓ | Similar issues as Android |
|
|
| Jellyfin Web | ✓ | N/A | ✓ | Full SSO support |
|
|
| Finamp (Music) | ✗ | ✓ | ✓ | No SSO, Quick Connect recommended |
|
|
| Jellyfin Kodi | ✗ | ✓ | ✓ | Token authentication works |
|
|
|
|
---
|
|
|
|
## 6. Testing and Troubleshooting
|
|
|
|
### 6.1 Testing Web Login
|
|
|
|
**Login URL:**
|
|
```
|
|
https://jellyfin.example.com/sso/OID/start/authentik
|
|
```
|
|
|
|
**Expected Flow:**
|
|
1. User navigates to URL
|
|
2. Redirects to Authentik login page
|
|
3. User authenticates with Authentik
|
|
4. Redirects back to Jellyfin
|
|
5. User is logged in with appropriate role
|
|
|
|
### 6.2 Adding SSO Button to Login Page
|
|
|
|
Create a custom login button on the Jellyfin login page:
|
|
|
|
1. Navigate to Dashboard → **General** → **Custom CSS**
|
|
2. Add the following CSS to create an SSO button:
|
|
|
|
```css
|
|
/* SSO Login Button */
|
|
.raised.emby-button {
|
|
padding: 0.9em 1em;
|
|
color: inherit !important;
|
|
}
|
|
|
|
.disclaimerContainer {
|
|
display: block;
|
|
}
|
|
```
|
|
|
|
3. Use browser developer tools or custom HTML injection to add button (plugin documentation has detailed instructions)
|
|
|
|
### 6.3 Common Errors and Solutions
|
|
|
|
#### Error: "Client authentication failed"
|
|
|
|
```
|
|
The registered client with id 'jellyfin' is configured to only support
|
|
'token_endpoint_auth_method' method 'client_secret_basic'.
|
|
```
|
|
|
|
**Solution:** Change Authentik provider settings:
|
|
- Edit OIDC Provider in Authentik
|
|
- Set **Client Authentication Method** to `client_secret_post`
|
|
- Save and restart Jellyfin
|
|
|
|
#### Error: "Incorrect role claims"
|
|
|
|
```
|
|
OpenID user "user123" has one or more incorrect role claims:
|
|
[{"Type": "groups", "Value": "jellyfin-user"}]. Expected any one of: ["jellyfin-users"]
|
|
```
|
|
|
|
**Solution:** Check exact spelling and case:
|
|
- Authentik groups must match exactly
|
|
- Plugin `<Roles>` must match exactly
|
|
- Claim name in `<RoleClaim>` must match Authentik scope mapping
|
|
|
|
#### Error: "Error processing request"
|
|
|
|
```
|
|
[ERR] Jellyfin.Api.Middleware.ExceptionMiddleware: Error processing request.
|
|
URL "GET" "/sso/OID/start/authentik"
|
|
```
|
|
|
|
**Common Causes:**
|
|
1. **DNS Resolution:** Jellyfin container cannot resolve Authentik hostname
|
|
2. **Network Connectivity:** Firewall blocking connection
|
|
3. **Certificate Issues:** SSL/TLS validation failing
|
|
|
|
**Solutions:**
|
|
- Verify DNS: `docker exec jellyfin ping auth.example.com`
|
|
- Check network connectivity
|
|
- Set `<DoNotValidateEndpoints>true</DoNotValidateEndpoints>` for testing (not production)
|
|
|
|
### 6.4 Debugging with Logs
|
|
|
|
Enable verbose logging in Jellyfin:
|
|
|
|
1. Dashboard → **Logs**
|
|
2. Look for `Jellyfin.Plugin.SSO_Auth` entries
|
|
3. Check for claim mismatches, authentication failures
|
|
|
|
**Useful Log Patterns:**
|
|
```
|
|
[INF] Jellyfin.Plugin.SSO_Auth.Api.SSOController: SSO Controller initialized
|
|
[WRN] OpenID user "username" has one or more incorrect role claims
|
|
[ERR] Error processing request
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Security Best Practices
|
|
|
|
### 7.1 HTTPS Configuration
|
|
|
|
**Always use HTTPS in production:**
|
|
- Configure reverse proxy (Traefik, Nginx, Caddy)
|
|
- Obtain valid SSL/TLS certificates
|
|
- Set `<DisableHttps>false</DisableHttps>`
|
|
|
|
### 7.2 Client Secret Security
|
|
|
|
**Protect the client secret:**
|
|
- Store securely in configuration files
|
|
- Use environment variables or secrets management
|
|
- Never commit to version control
|
|
- Rotate periodically
|
|
|
|
### 7.3 Endpoint Validation
|
|
|
|
**Enable validation in production:**
|
|
```xml
|
|
<DoNotValidateEndpoints>false</DoNotValidateEndpoints>
|
|
<DoNotValidateIssuerName>false</DoNotValidateIssuerName>
|
|
```
|
|
|
|
**Disable only for testing/debugging**
|
|
|
|
### 7.4 Role-Based Access Control
|
|
|
|
**Implement least privilege:**
|
|
- Separate admin and user roles
|
|
- Use folder permissions for content restriction
|
|
- Enable `<EnableAuthorization>true</EnableAuthorization>`
|
|
- Audit user access regularly
|
|
|
|
### 7.5 API Token Management
|
|
|
|
**For mobile apps using tokens:**
|
|
- Generate device-specific tokens
|
|
- Use descriptive names: "iPhone - John's Device"
|
|
- Revoke tokens for lost devices
|
|
- Set token expiration if supported
|
|
- Monitor active sessions
|
|
|
|
---
|
|
|
|
## 8. Advanced Configuration Options
|
|
|
|
### 8.1 Folder-Based Role Mapping
|
|
|
|
Restrict access to specific libraries based on roles:
|
|
|
|
```xml
|
|
<EnableFolderRoles>true</EnableFolderRoles>
|
|
<FolderRoleMappings>
|
|
<FolderRoleMappings>
|
|
<Role>kids-content</Role>
|
|
<Folders>
|
|
<string>Kids Movies</string>
|
|
<string>Kids TV Shows</string>
|
|
</Folders>
|
|
</FolderRoleMappings>
|
|
</FolderRoleMappings>
|
|
```
|
|
|
|
### 8.2 Canonical User Links
|
|
|
|
Link SSO users to existing Jellyfin accounts:
|
|
|
|
```xml
|
|
<CanonicalLinks>
|
|
<item>
|
|
<key>
|
|
<string>sso-username</string>
|
|
</key>
|
|
<value>
|
|
<guid>existing-jellyfin-user-guid</guid>
|
|
</value>
|
|
</item>
|
|
</CanonicalLinks>
|
|
```
|
|
|
|
### 8.3 Live TV Permissions
|
|
|
|
Control Live TV access via roles:
|
|
|
|
```xml
|
|
<EnableLiveTv>true</EnableLiveTv>
|
|
<EnableLiveTvRoles>true</EnableLiveTvRoles>
|
|
<LiveTvRoles>
|
|
<string>livetv-users</string>
|
|
</LiveTvRoles>
|
|
<EnableLiveTvManagement>true</EnableLiveTvManagement>
|
|
<LiveTvManagementRoles>
|
|
<string>jellyfin-admins</string>
|
|
</LiveTvManagementRoles>
|
|
```
|
|
|
|
### 8.4 Port Override
|
|
|
|
Override the default port for callback URLs:
|
|
|
|
```xml
|
|
<PortOverride>8096</PortOverride>
|
|
```
|
|
|
|
Useful when Jellyfin runs behind a reverse proxy on a non-standard port.
|
|
|
|
---
|
|
|
|
## 9. Integration Testing Checklist
|
|
|
|
- [ ] Plugin installed and Jellyfin restarted
|
|
- [ ] Authentik OIDC provider configured with correct redirect URI
|
|
- [ ] Client authentication method set to `client_secret_post`
|
|
- [ ] Groups scope enabled in Authentik
|
|
- [ ] Test users assigned to jellyfin-users or jellyfin-admins groups
|
|
- [ ] Plugin configured with correct endpoint, client ID, and secret
|
|
- [ ] Role claim mapping matches Authentik group claim
|
|
- [ ] Web login successful via `/sso/OID/start/authentik`
|
|
- [ ] User receives correct permissions (admin vs. user)
|
|
- [ ] Quick Connect enabled for mobile apps
|
|
- [ ] API tokens generated for mobile testing
|
|
- [ ] Mobile app authentication tested
|
|
- [ ] HTTPS enabled in production
|
|
- [ ] Endpoint validation enabled
|
|
- [ ] Logs reviewed for errors
|
|
|
|
---
|
|
|
|
## 10. References and Resources
|
|
|
|
**Official Documentation:**
|
|
- Jellyfin SSO Plugin Repository: https://github.com/9p4/jellyfin-plugin-sso
|
|
- Authentik Jellyfin Integration: https://docs.goauthentik.io/integrations/services/jellyfin/
|
|
- Jellyfin Official Documentation: https://jellyfin.org/docs/
|
|
|
|
**Community Resources:**
|
|
- Plugin Issue Tracker: https://github.com/9p4/jellyfin-plugin-sso/issues
|
|
- Jellyfin Forum: https://forum.jellyfin.org/
|
|
- Authentik Forum: https://github.com/goauthentik/authentik/discussions
|
|
|
|
**Key Issues Referenced:**
|
|
- Mobile App SSO Issue #189: https://github.com/9p4/jellyfin-plugin-sso/issues/189
|
|
- Authelia Configuration Discussion: https://www.authelia.com/integration/openid-connect/clients/jellyfin/
|
|
- Quick Connect Feature Request: https://support.symfonium.app/t/quick-connect-for-jellyfin/6428
|
|
|
|
---
|
|
|
|
## 11. Conclusion
|
|
|
|
The Jellyfin SSO-Auth plugin provides robust OIDC integration with Authentik for web-based authentication. Key takeaways:
|
|
|
|
1. **Web authentication works well** when properly configured with correct claim mappings
|
|
2. **Mobile app support is limited** - Quick Connect or API tokens are required for mobile access
|
|
3. **Role-based authorization** requires exact matching between Authentik groups and plugin configuration
|
|
4. **Security configuration** is critical - always use HTTPS and validate endpoints in production
|
|
5. **Troubleshooting** relies heavily on log analysis and understanding OIDC claim flows
|
|
|
|
**Recommended Deployment Strategy:**
|
|
- Primary users: SSO via web interface
|
|
- Mobile apps: Quick Connect for initial setup, API tokens for ongoing access
|
|
- Administrators: SSO + 2FA in Authentik for enhanced security
|
|
- Regular audits of active sessions and API tokens
|
|
|
|
This configuration provides a secure, user-friendly authentication experience while accommodating the limitations of mobile client applications.
|
|
|
|
---
|
|
|
|
**Document Version:** 1.0
|
|
**Last Updated:** 2026-01-20
|
|
**Author:** Research Task RESEARCH-004
|
|
**Status:** Complete
|