# Addendum: Technical Context for Downstream Documents Carries the detail that does not belong in `prd.md`. The brief's addendum (`_bmad-output/briefs/.../addendum.md`) holds the original context; this file adds what the PRD discovery produced. ## Existing picture pipeline (the three PowerShell scripts stay unchanged) - `AD-ProfilePicture-Sync.ps1` (DC, scheduled task): for every user in the target OU reads `.jpg` from the source path, else a default image. It writes `_96.jpg` and `_448.jpg` to the processed path, writes `.md5` (MD5 of the source file) there, and sets `thumbnailPhoto`, `jpegPhoto` and `photo` from the 96px copy (limit 100 KB). It never compares the MD5, so every run reprocesses every user. - `Set-LocalAccountPicture.ps1` (logon): builds Windows account-picture sizes from `thumbnailPhoto`; large sizes use the 448px copy from the share. - `Set-AccountPictureRegistry-System.ps1` (startup): applies registry entries from manifests. - The original scripts are in `context-resources/` (untracked in git). Verified against them: the MD5 file is written at line 114 and the AD attributes at line 117, so a failed AD write still leaves a matching MD5 file. ## Portal and the pipeline: contract - Portal writes: `/.jpg`, square JPEG, at least 448 px (assumed 512×512). - Portal reads: `/.md5` to detect that the Sync Task has processed the file (the hash is the MD5 of the Portal's file). This ties the Portal to the unchanged script. - The hash in `.md5` is an uppercase hex MD5 written with a trailing newline (`Get-FileHash` plus `Set-Content`). Compare case-insensitively and trim whitespace. - The sync script covers `OU=Organisation`, which includes the Portal's writable OU. File names use `sAMAccountName`. - Portal reads: `thumbnailPhoto` from Active Directory to show the current picture. - Both paths are configuration. ## Active Directory - Writable OU: configurable; example in the homelab: `OU=Clients,OU=Organisation,DC=ping-mee,DC=local`. - Attributes written: `givenName`, `sn`, `displayName`, `mail`, `telephoneNumber`, `mobile`, and the password via LDAPS. - The Service Account needs delegated rights for exactly those attributes and password change on that OU. Password writes need LDAPS. - Read rights also needed: `pwdLastSet`, account enabled and locked state, group membership, `thumbnailPhoto`, and the Password Policy shown on the password page (domain `minPwdLength`, `pwdProperties`, `pwdHistoryLength`, and the user's `msDS-ResultantPSO` for a fine-grained policy). [Attribute names to verify in the test OU.] - Expired and "must change" passwords: AD refuses the bind (LDAP error 49, data 532 or 773). The Portal does not handle these. The Admin resets the password in AD. - authentik's LDAP source offers its own password writeback to AD (needs `ldaps://` and delegated rights). Not used; the Portal changes passwords itself. Source: authentik Active Directory and LDAP source docs. ## Identity and roles - OIDC via authentik, but kept generic so another provider works. - `preferred_username` equals `sAMAccountName` (confirmed identical in the homelab). - Roles: the Portal checks Publisher and Admin group membership in Active Directory. ## Security notes - Throttling happens in front of every bind, to avoid lockouts by attackers. - E-mail change chain risk (hijacked session, e-mail change, reset via e-mail) mitigated by: current password required, confirmation to the new address, notice and 24-hour Undo Link to the old address, undo ends sessions and notifies the Admin. - Picture handling: HEIC, WebP, PNG and JPEG only; SVG rejected because it can carry scripts and external references. Decode with size and pixel limits; strip metadata; never serve originals. - Markdown in Announcements is rendered with sanitization. - Secrets only in Docker environment variables. ## Candidate technical choices (not decided) - Embedded database (for example SQLite) in a mounted volume is enough for ten users; a server database could be a later option. - A server-side image library with HEIC support is required. - SMB access from a Linux container: a mounted share is the simplest. ## Design - Office 365 (Fluent) look, not OWA 2010 or Aero. Themes and backgrounds are Admin-managed.