Add opt-in milestone and failure emails for background tasks #9

Closed
opened 2026-10-24 13:27:15 +00:00 by jchapman · 5 comments
Owner

Analysis and preview can take long enough that users should be able to leave and receive an actionable notification.

Acceptance criteria:

  • Offer a per-operation choice beside the activity panel, adjustable while work runs: “Email me when my analysis is ready to review”, “Email me when my preview is ready to approve”, or “Email me when my import finishes”.
  • Explain that opting in also covers a failure requiring attention. Distinguish failure, cancellation and successful completion.
  • Use the configured external SMTP relay and branding. Require explicit consent and a verified provider email or supported administrator-confirmed local address; an OIDC email claim alone is insufficient.
  • Show a masked destination and a useful unavailable state if delivery cannot be enabled. Do not accept arbitrary recipients or silently copy administrators.
  • Use durable, idempotent notification scheduling with retry behavior that avoids duplicate mail. Email failure must not change the task’s processing result.
  • Link to authenticated results without tokens, private paths or media details. Never advance to import automatically.
  • Test ownership, verified-address rules, consent changes, worker retries and cancellation/completion races.
Analysis and preview can take long enough that users should be able to leave and receive an actionable notification. Acceptance criteria: - Offer a per-operation choice beside the activity panel, adjustable while work runs: “Email me when my analysis is ready to review”, “Email me when my preview is ready to approve”, or “Email me when my import finishes”. - Explain that opting in also covers a failure requiring attention. Distinguish failure, cancellation and successful completion. - Use the configured external SMTP relay and branding. Require explicit consent and a verified provider email or supported administrator-confirmed local address; an OIDC email claim alone is insufficient. - Show a masked destination and a useful unavailable state if delivery cannot be enabled. Do not accept arbitrary recipients or silently copy administrators. - Use durable, idempotent notification scheduling with retry behavior that avoids duplicate mail. Email failure must not change the task’s processing result. - Link to authenticated results without tokens, private paths or media details. Never advance to import automatically. - Test ownership, verified-address rules, consent changes, worker retries and cancellation/completion races.
Author
Owner

Starting #9 after reading #14, this issue, and the related authentication, activity/cancellation and diagnostics handoffs. Scope: explicit per-operation consent beside activity, verified owner destinations, durable scheduling from authoritative terminal task states, safe SMTP retry/uncertainty handling, branded authenticated links, and ownership/consent/outcome race tests. Working on an isolated branch combining the reviewed #6 and #4/#7/#8 prerequisites; issue #12 is on hold and is excluded. No pilot rebuild, restart or active task interruption is planned.

Starting #9 after reading #14, this issue, and the related authentication, activity/cancellation and diagnostics handoffs. Scope: explicit per-operation consent beside activity, verified owner destinations, durable scheduling from authoritative terminal task states, safe SMTP retry/uncertainty handling, branded authenticated links, and ownership/consent/outcome race tests. Working on an isolated branch combining the reviewed #6 and #4/#7/#8 prerequisites; issue #12 is on hold and is excluded. No pilot rebuild, restart or active task interruption is planned.
Author
Owner

Implementation finding: the existing verified-address and external-relay support can be reused, but SMTP acceptance uncertainty must not be retried blindly. The task outbox records one consent/delivery identity per operation, retries confirmed non-acceptance up to five attempts, and exposes uncertain handoffs without automatically resending. Cancellation suppresses milestone mail; completion winning a late stop uses the actual terminal outcome. The initial full backend suite passed; race and browser checks are continuing. Scope clarification from the owner: use normal routable collection/analysis/attempt URLs. Direct page loads, history navigation and return to the selected page after sign-in are being covered. Issue #12 remains excluded; no pilot services or active tasks have been restarted.

Implementation finding: the existing verified-address and external-relay support can be reused, but SMTP acceptance uncertainty must not be retried blindly. The task outbox records one consent/delivery identity per operation, retries confirmed non-acceptance up to five attempts, and exposes uncertain handoffs without automatically resending. Cancellation suppresses milestone mail; completion winning a late stop uses the actual terminal outcome. The initial full backend suite passed; race and browser checks are continuing. Scope clarification from the owner: use normal routable collection/analysis/attempt URLs. Direct page loads, history navigation and return to the selected page after sign-in are being covered. Issue #12 remains excluded; no pilot services or active tasks have been restarted.
Author
Owner

Implemented and published for review: commit ba40ae4e90ee0c4b3b9c51b3bd3eb1236b20bbd3, branch codex/issue-9-task-emails, PR #20: #20 . Working tree is clean.

Changes:

  • Separate explicit consent beside analysis/preview/import activity, adjustable from owner sessions while work runs; masked verified destination, useful relay/address unavailable states, and fresh consent for every new run. Arbitrary recipients are rejected. Task mail never copies administrators.
  • Durable SQLite consent/outbox, one delivery identity per operation, terminal-state reconciliation and preservation of the preceding outcome when analysis is retried. Success, warnings, failure and interruption remain distinct; confirmed cancellation sends no milestone email. Successful completion can win a late stop. Email failure never changes processing results.
  • Five bounded attempts for confirmed SMTP non-acceptance, stable Message-ID, and visible uncertainty after a lost acceptance reply, interrupted handoff or failed post-handoff database save. Uncertain handoffs are not automatically resent. Consent withdrawal before claim prevents delivery; mail already handed off cannot be recalled. Collection deletion removes its outbox/history.
  • Per the owner's clarification, normal routable collection, analysis-run and import/preview-attempt URLs, direct reload and Back/Forward. Historical attempt links select their own result; an overwritten analysis explicitly identifies the newer run. OIDC preserves an allowlisted internal page across sign-in. Email contains broad outcome and authenticated URL only, with no media details, private paths or tokens. No automatic import or replay.

Checks actually passed locally:

  • Final full backend tests and vet in Linux AMD64 containers, including pinned-importer fixtures; focused notification/authentication/SMTP/task lifecycle/collection-deletion race tests. Ownership includes real signed-in owner/other-user/administrator and origin checks. Tests cover consent changes, verified-address rules, database failure, worker retry, restart/uncertainty, concurrent claims and cancellation/completion races.
  • TLS and STARTTLS fake relay tests: one owner recipient, branding, stable Message-ID, definite rejection and dropped DATA acceptance response. No real emails were sent.
  • UI lint/build; focused task-email, task-activity and OIDC browser suites; two owner sessions, reconnect/conflicts, unavailable states, three consent labels, mobile screenshot/layout, historical URLs and Back/Forward. Screenshot inspected.
  • Disposable complete browser/queue/SQLite/upload-recovery/admin-settings walkthrough; final direct-route and unavailable-relay stack checks; production HTTPS/proxy/readiness/restart-resume checks. Only disposable resources were restarted and their containers/volumes were removed.
  • Nine CI contract/policy tests, documentation/source-path checks, formatting/diff checks and full-history secret scan (37 commits, no leaks). The initial contract run lacked PyYAML; rerunning with the repository's hash-pinned dependency passed.
  • Final source gosec/govulncheck policies: 38 production files, 29 previously reviewed findings, no suppressions/new exceptions. Final application image advisory policy passed against a freshly updated database. Existing baselines and release rules are unchanged.

State and next handoff:
Published for review, not merged, release-image-published or deployed. PR #20 is based on #17 and includes the existing #18 metadata changes through prerequisite merge 54479e0; #15/#16 are transitive dependencies. Issue #12 is excluded and remains on hold. Review the issue #9 feature commit, integrate the prerequisites, then retarget to main and verify the resulting diff.

Forgejo run https://git.sharedroot.net/jchapman/Immich-Bridge/actions/runs/9 is waiting for native validation. Native ARM64, real-provider inbox delivery and deployed pilot behavior remain unverified; the existing UI bundle-size advisory remains. No pilot service, active upload or server task was interrupted. Coordinate an idle deployment/restart and verify an opted-in owner task using the actual relay before closing #9. This issue stays open.

Implemented and published for review: commit `ba40ae4e90ee0c4b3b9c51b3bd3eb1236b20bbd3`, branch `codex/issue-9-task-emails`, PR #20: https://git.sharedroot.net/jchapman/Immich-Bridge/pulls/20 . Working tree is clean. Changes: - Separate explicit consent beside analysis/preview/import activity, adjustable from owner sessions while work runs; masked verified destination, useful relay/address unavailable states, and fresh consent for every new run. Arbitrary recipients are rejected. Task mail never copies administrators. - Durable SQLite consent/outbox, one delivery identity per operation, terminal-state reconciliation and preservation of the preceding outcome when analysis is retried. Success, warnings, failure and interruption remain distinct; confirmed cancellation sends no milestone email. Successful completion can win a late stop. Email failure never changes processing results. - Five bounded attempts for confirmed SMTP non-acceptance, stable Message-ID, and visible uncertainty after a lost acceptance reply, interrupted handoff or failed post-handoff database save. Uncertain handoffs are not automatically resent. Consent withdrawal before claim prevents delivery; mail already handed off cannot be recalled. Collection deletion removes its outbox/history. - Per the owner's clarification, normal routable collection, analysis-run and import/preview-attempt URLs, direct reload and Back/Forward. Historical attempt links select their own result; an overwritten analysis explicitly identifies the newer run. OIDC preserves an allowlisted internal page across sign-in. Email contains broad outcome and authenticated URL only, with no media details, private paths or tokens. No automatic import or replay. Checks actually passed locally: - Final full backend tests and vet in Linux AMD64 containers, including pinned-importer fixtures; focused notification/authentication/SMTP/task lifecycle/collection-deletion race tests. Ownership includes real signed-in owner/other-user/administrator and origin checks. Tests cover consent changes, verified-address rules, database failure, worker retry, restart/uncertainty, concurrent claims and cancellation/completion races. - TLS and STARTTLS fake relay tests: one owner recipient, branding, stable Message-ID, definite rejection and dropped DATA acceptance response. No real emails were sent. - UI lint/build; focused task-email, task-activity and OIDC browser suites; two owner sessions, reconnect/conflicts, unavailable states, three consent labels, mobile screenshot/layout, historical URLs and Back/Forward. Screenshot inspected. - Disposable complete browser/queue/SQLite/upload-recovery/admin-settings walkthrough; final direct-route and unavailable-relay stack checks; production HTTPS/proxy/readiness/restart-resume checks. Only disposable resources were restarted and their containers/volumes were removed. - Nine CI contract/policy tests, documentation/source-path checks, formatting/diff checks and full-history secret scan (37 commits, no leaks). The initial contract run lacked PyYAML; rerunning with the repository's hash-pinned dependency passed. - Final source gosec/govulncheck policies: 38 production files, 29 previously reviewed findings, no suppressions/new exceptions. Final application image advisory policy passed against a freshly updated database. Existing baselines and release rules are unchanged. State and next handoff: Published for review, not merged, release-image-published or deployed. PR #20 is based on #17 and includes the existing #18 metadata changes through prerequisite merge `54479e0`; #15/#16 are transitive dependencies. Issue #12 is excluded and remains on hold. Review the issue #9 feature commit, integrate the prerequisites, then retarget to main and verify the resulting diff. Forgejo run https://git.sharedroot.net/jchapman/Immich-Bridge/actions/runs/9 is waiting for native validation. Native ARM64, real-provider inbox delivery and deployed pilot behavior remain unverified; the existing UI bundle-size advisory remains. No pilot service, active upload or server task was interrupted. Coordinate an idle deployment/restart and verify an opted-in owner task using the actual relay before closing #9. This issue stays open.
Author
Owner

Integration handoff: PR #20 is merged into main in f9885d4. The final combined source passed local backend/vet/race, UI/browser, container/isolation/HTTPS, source/image policy and secret checks. Detailed merge/conflict evidence and limitations: #14 (comment). Native Forgejo AMD64/ARM64 release validation remains queued; no release images or deployment are claimed. This issue remains open for its pilot checkpoint. Verify an opted-in owner task with the actual configured relay and authenticated result link after coordinated deployment. No active upload/task or pilot service was interrupted.

Integration handoff: PR #20 is merged into main in `f9885d4`. The final combined source passed local backend/vet/race, UI/browser, container/isolation/HTTPS, source/image policy and secret checks. Detailed merge/conflict evidence and limitations: https://git.sharedroot.net/jchapman/Immich-Bridge/issues/14#issuecomment-175. Native Forgejo AMD64/ARM64 release validation remains queued; no release images or deployment are claimed. This issue remains open for its pilot checkpoint. Verify an opted-in owner task with the actual configured relay and authenticated result link after coordinated deployment. No active upload/task or pilot service was interrupted.
Author
Owner

Final development handoff: PR #20 is merged into main in f9885d4, preserving feature commit(s) ba40ae4.

Fresh per-operation email consent is bound to the verified owner destination, with no arbitrary recipient or administrator copy. The durable outbox uses terminal outcomes, suppresses confirmed cancellation, bounds definite-rejection retries and leaves ambiguous handoffs uncertain. Authenticated result links preserve reload/history/sign-in return.

Validation: Notification/SMTP/auth/lifecycle/ownership/origin and concurrent-claim races passed, including fake TLS/STARTTLS relays, lost acceptance, database recovery and fresh retry consent. Task-email browser and HTTPS route checks passed. No real email was sent. The combined application also passed backend/vet/race, UI lint/build, container/HTTPS, source/image policies and secret checks; integration evidence.

Documentation is updated on main through PR #21, merge 5ed7191: feature guide, merged scope/evidence, and remaining pilot checks. All nine documentation/policy tests and link/anchor/workflow checks passed.

Closing at the owner's explicit request after merge, local validation and documentation review. This supersedes the earlier request to keep this development issue open through deployment. Native Forgejo AMD64/ARM64 release gates, coordinated idle installation and applicable real-provider/owner pilot checks remain in the release checklist and coordination issue #14. No deployment, native ARM64 pass, real-library capacity result or gate waiver is claimed. PR #19 and scanning remain on hold.

Final development handoff: [PR #20](https://git.sharedroot.net/jchapman/Immich-Bridge/pulls/20) is merged into main in `f9885d4`, preserving feature commit(s) `ba40ae4`. Fresh per-operation email consent is bound to the verified owner destination, with no arbitrary recipient or administrator copy. The durable outbox uses terminal outcomes, suppresses confirmed cancellation, bounds definite-rejection retries and leaves ambiguous handoffs uncertain. Authenticated result links preserve reload/history/sign-in return. Validation: Notification/SMTP/auth/lifecycle/ownership/origin and concurrent-claim races passed, including fake TLS/STARTTLS relays, lost acceptance, database recovery and fresh retry consent. Task-email browser and HTTPS route checks passed. No real email was sent. The combined application also passed backend/vet/race, UI lint/build, container/HTTPS, source/image policies and secret checks; [integration evidence](https://git.sharedroot.net/jchapman/Immich-Bridge/issues/14#issuecomment-175). Documentation is updated on main through [PR #21](https://git.sharedroot.net/jchapman/Immich-Bridge/pulls/21), merge `5ed7191`: [feature guide](https://git.sharedroot.net/jchapman/Immich-Bridge/src/branch/main/docs/email.md#opt-in-task-notifications), [merged scope/evidence](https://git.sharedroot.net/jchapman/Immich-Bridge/src/branch/main/docs/integration-status.md), and [remaining pilot checks](https://git.sharedroot.net/jchapman/Immich-Bridge/src/branch/main/docs/deployment.md#merged-pilot-feature-checks). All nine documentation/policy tests and link/anchor/workflow checks passed. Closing at the owner's explicit request after merge, local validation and documentation review. This supersedes the earlier request to keep this development issue open through deployment. Native Forgejo AMD64/ARM64 release gates, coordinated idle installation and applicable real-provider/owner pilot checks remain in the release checklist and coordination issue #14. No deployment, native ARM64 pass, real-library capacity result or gate waiver is claimed. PR #19 and scanning remain on hold.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jchapman/Immich-Bridge#9
No description provided.