Skip to content

fix(den): remove download links from invite emails#2673

Merged
OmarMcAdam merged 1 commit into
devfrom
email-invites-remove-download-link
Jul 13, 2026
Merged

fix(den): remove download links from invite emails#2673
OmarMcAdam merged 1 commit into
devfrom
email-invites-remove-download-link

Conversation

@OmarMcAdam

Copy link
Copy Markdown
Collaborator

Summary

  • remove the desktop download section from organization invitation emails
  • stop generating organization install links for invitation delivery
  • update invitation email tests and eval coverage

Validation

  • pnpm --filter @openwork-ee/den-api exec bun test test/organization-invite-email.test.ts — passed
  • pnpm --filter @openwork-ee/den-api exec tsc -p tsconfig.json --noEmit — passed
  • node --check evals/flows/email-invites-remove-download-link.flow.mjs — passed
  • node --check evals/flows/invite-to-desktop.flow.mjs — passed
  • pnpm fraimz --flow email-invites-remove-download-link --stack den --cdp-url http://127.0.0.1:9823 — passed

Proof

Fraimz passed with validated screenshots of the rendered invitation email. The proof will be posted as a PR comment.

@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment Jul 11, 2026 9:56am
openwork-den Ready Ready Preview, Comment Jul 11, 2026 9:56am
openwork-den-worker-proxy Ready Ready Preview, Comment Jul 11, 2026 9:56am
openwork-landing Ready Ready Preview, Comment, Open in v0 Jul 11, 2026 9:56am

@OmarMcAdam

Copy link
Copy Markdown
Collaborator Author

fraimz — ✅ PASSED

1 passed · 0 failed · 0 skipped — run 2026-07-11T09-55-19-205Z

Full frame proof with validated screenshots: evals/results/2026-07-11T09-55-19-205Z/fraimz.html (re-run: pnpm fraimz --flow email-invites-remove-download-link)

✅ email-invites-remove-download-link — Invitation emails stay focused on joining the workspace

User-facing flow demo

  • ✅ A generic CDP browser endpoint is available for rendered-email screenshots
  • ✅ Alex can load the organization
  • ✅ The invitation identifies its workspace
  • ✅ The Den token resolves to an inviter email for the invite email
  1. Alex sends Maya a workspace invitation and the real email names that workspace

    🎙 An invited user receives an OpenWork workspace invitation email with the workspace details and Join workspace button.

    • ✅ Alex can load the organization
    • ✅ The invitation identifies its workspace
    • ✅ The Den token resolves to an inviter email for the invite email
    • ✅ Maya's invitation is created through POST /v1/invitations
    • ✅ The invitation API returns Maya's email
    • ✅ The invitation API assigns Maya the member role
    • ✅ Alex can load the organization
    • ✅ The invitation identifies its workspace
    • ✅ The Den token resolves to an inviter email for the invite email
    • ✅ Maya's invitation is pending in /v1/org
    • ✅ The dev outbox contains Maya's resulting organizationInvite email
    • ✅ Maya's invitation is the newest rendered organization email
    • ✅ The rendered invitation email is available
    • ✅ The invitation email contains an Accept invite join link
    • ✅ The invite link is parsed against the Den API origin
    • ✅ The invite email CTA targets the join page
    • ✅ The invite link carries an opaque invite credential
    • ✅ Published email evidence redacts the invitation credential
    • ✅ Alex can load the organization
    • ✅ The invitation identifies its workspace
    • ✅ The Den token resolves to an inviter email for the invite email
    • ✅ Maya's invitation is pending in /v1/org
    • ✅ The invitation email names its workspace
    • ✅ The invitation email keeps the accept action
    • ✅ The invitation email includes inviter email details
    • ✅ The invitation email includes inviter name details
    • ✅ The invitation email explains who is inviting Maya to the workspace
    • ✅ Visible text includes "Join OpenWork"
    • ✅ Visible text includes "Accept invite"
    • ✅ Visible text includes "alex@acme.test"
    • 📸 email-invites-remove-download-link-01-email-invite-join-action.png — 6 validations passed
    • ✅ A generic CDP browser endpoint is available for rendered-email screenshots
  2. Maya's real invitation email is join-focused and has no desktop download link

    🎙 The email contains no desktop download prompt or download link, keeping the invitation focused on joining.

    • ✅ Published email evidence redacts the invitation credential
    • ✅ The lower invite email content is framed for the absence proof
    • ✅ The invitation email omits desktop/download copy: Download the desktop app
    • ✅ The invitation email omits desktop/download copy: Download OpenWork
    • ✅ The invitation email omits desktop/download copy: Edit spreadsheets
    • ✅ The invitation email omits desktop/download copy: Control your browser
    • ✅ The invitation email omits desktop/download copy: Organize files
    • ✅ The invitation email omits desktop/download copy: Automate tasks
    • ✅ The invitation email omits desktop/download copy: desktop app
    • ✅ The invitation email omits desktop/download copy: Open OpenWork
    • ✅ The invitation email omits desktop/download copy: Install OpenWork
    • ✅ The invitation email omits desktop/download copy: Install the desktop app
    • ✅ The invitation email has no organization install token link
    • ✅ The invitation email has no generic desktop download link
    • ✅ The invitation email contains no download or install hrefs
    • ✅ Visible text includes "If the button does not work"
    • ✅ Visible text does not include "Download the desktop app"
    • ✅ Visible text does not include "Download OpenWork"
    • ✅ Visible text does not include "Edit spreadsheets"
    • ✅ Visible text does not include "Control your browser"
    • ✅ Visible text does not include "Organize files"
    • ✅ Visible text does not include "Automate tasks"
    • ✅ Visible text does not include "desktop app"
    • ✅ Visible text does not include "Open OpenWork"
    • ✅ Visible text does not include "Install OpenWork"
    • ✅ Visible text does not include "Install the desktop app"
    • ✅ The rendered email page has no download or install links
    • 📸 email-invites-remove-download-link-02-email-invite-no-desktop-downloads.png — 15 validations passed
    • ✅ Script frame 1 narrated: "An invited user receives an OpenWork workspace invitation email with the workspace detai"
    • ✅ Script frame 2 narrated: "The email contains no desktop download prompt or download link, keeping the invitation f"

(screenshot upload failed: BLOB_READ_WRITE_TOKEN is not set and could not be fetched from Infisical (infisical secrets get BLOB_READ_WRITE_TOKEN --plain --silent) — run infisical login once, or export it: export BLOB_READ_WRITE_TOKEN="$(infisical secrets get BLOB_READ_WRITE_TOKEN --plain --silent)" — images available in the run directory)

Copy link
Copy Markdown
Member

Scope note from the MCP diagnostics validation pass:

This invite-email/download change is unrelated to the ServiceNow MCP connection work, so it was not included in the Daytona MCP test matrix. I am not making a merge recommendation for this PR based on that validation, and no branch or merge mutation was performed here.

@Pablosinyores Pablosinyores left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, the removal is complete across the whole chain, which is the part that usually gets missed: the payload drops downloadUrl in both auth.ts and invitations.ts, and the template drops it in lockstep — the downloadUrl? prop, the DEFAULT_OPENWORK_DOWNLOAD_URL default, the desktop Section, and the now-unused desktopSection styles all go together. So there's no dangling downloadUrl left to render as undefined or fall back to the default download button. The eval rename (invite-email-org-install-linkemail-invites-remove-download-link) plus the separate invite-to-desktop.flow updates make it clear the scope is intentionally org-invite-only and desktop-invite links stay — good, that's the right boundary.

One loose end worth deciding on: after this, resolveInvitationDownloadUrl in install-links.ts has no production caller left — its only two call sites (auth.ts, invitations.ts) are exactly what this PR removes, and the sole remaining reference is test/install-link-access.test.ts. So it's now dead in production but still carries a test exercising it. Either drop the function and that test, or keep them intentionally (e.g. you plan to reuse the minting logic) and it's worth a one-line note so the next person doesn't read it as accidentally-orphaned. Same question for DEFAULT_OPENWORK_DOWNLOAD_URL / desktopCapabilities in desktop-capabilities.js — if this template was their last consumer they're now unused too; if the desktop-invite flow still imports them, ignore this.

Not blocking — the user-facing change and its safety look right. Just flagging the dead-code tail so it doesn't accumulate.

@OmarMcAdam OmarMcAdam merged commit c7b78f9 into dev Jul 13, 2026
15 checks passed
@OmarMcAdam

Copy link
Copy Markdown
Collaborator Author

Nice, the removal is complete across the whole chain, which is the part that usually gets missed: the payload drops downloadUrl in both auth.ts and invitations.ts, and the template drops it in lockstep — the downloadUrl? prop, the DEFAULT_OPENWORK_DOWNLOAD_URL default, the desktop Section, and the now-unused desktopSection styles all go together. So there's no dangling downloadUrl left to render as undefined or fall back to the default download button. The eval rename (invite-email-org-install-linkemail-invites-remove-download-link) plus the separate invite-to-desktop.flow updates make it clear the scope is intentionally org-invite-only and desktop-invite links stay — good, that's the right boundary.

One loose end worth deciding on: after this, resolveInvitationDownloadUrl in install-links.ts has no production caller left — its only two call sites (auth.ts, invitations.ts) are exactly what this PR removes, and the sole remaining reference is test/install-link-access.test.ts. So it's now dead in production but still carries a test exercising it. Either drop the function and that test, or keep them intentionally (e.g. you plan to reuse the minting logic) and it's worth a one-line note so the next person doesn't read it as accidentally-orphaned. Same question for DEFAULT_OPENWORK_DOWNLOAD_URL / desktopCapabilities in desktop-capabilities.js — if this template was their last consumer they're now unused too; if the desktop-invite flow still imports them, ignore this.

Not blocking — the user-facing change and its safety look right. Just flagging the dead-code tail so it doesn't accumulate.

bro wtf is this slop

reachjalil added a commit that referenced this pull request Jul 13, 2026
* feat(den): connect marketplace plugin MCPs

* fix(app): preserve attachment request metadata (#2704)

* fix(app): prompt when selected model is unavailable (#2706)

* fix(app): use reported model thinking levels (#2707)

* ignore: update download stats 2026-07-13

* feat(inference): add Sentry request diagnostics (#2708)

* feat(inference): remove Fusion model (#2710)

* feat(den): add configurable observability (#2703)

* feat(inference): report unknown usage models (#2712)

* chore: bump version to 0.17.21

* chore(aur): update PKGBUILD for 0.17.21

* fix(app): keep app name out of wordmark slot

* fix(den): remove download links from invite emails (#2673)

* chore: bump version to 0.17.22

* docs(helm): add OTEL setup guide (#2713)

* chore(aur): update PKGBUILD for 0.17.22

* feat(mcp): add deployable enterprise diagnostics endpoint (#2702)

* feat(mcp): add deployable diagnostics endpoint

* feat(den): add private-cloud egress diagnostics

* Harden deployable MCP diagnostics preview

* Fix diagnostics lockfile after dev sync

* Support deployment-specific Vercel preview origins

* Default Den diagnostics to OpenWork Labs

* Store diagnostic token in Den

* Add diagnostics dashboard login

* Sync diagnostics credential migration

* fix(den): avoid duplicate signup verification emails (#2714)

* chore: bump version to 0.17.23

* chore(aur): update PKGBUILD for 0.17.23

* feat(helm): pass Node options to den-api (#2715)

* feat(helm): pass Node options to den-api

* docs(helm): document den-api Node options

* chore: bump version to 0.17.24

* chore(aur): update PKGBUILD for 0.17.24

* Revert "feat: deterministic air-gapped organization installer (#2668)"

This reverts commit e8ab197.

---------

Co-authored-by: Omar McAdam <gh@mcadam.io>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: OpenWork Release Bot <release-bot@users.noreply.github.com>
Co-authored-by: Jalil <reachjalil@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants