BuiltEmail workspace

Employee payroll welcome contract

Implementation: App\Mail\welcomeEmployee. View: resources/views/emails/payroll/welcomeEmployee.blade.php. Shared original wrapper: mail::message. Purpose: tell an employee that their employer registered them on Built and provide their payroll-portal login details.

Usage evidence: app/Http/Controllers/Payroll/employeesController.php:348; app/Imports/EmployeeImport.php:57; app/Imports/EmployeeImportKE.php:65; app/Jobs/ImportEmployeesBulkJob.php:186. These static references are evidence, not proof of current production delivery.

Suggested subject: {{subject_business_name}}: Your Registration (existing business-name header pattern).

Suggested preheader: Your employer registered you on Built. Your payroll portal sign-in details are included.

Portable placeholder contract

TokenExisting source / derivationHandling
{{logo_url}}Original Built app_name PNGOptional deployment override; concrete project HTTPS PNG is already present. Approved absolute HTTPS or matching attached CID only.
{{preheader}}Suggested text above, based only on existing registration/access contextRequired escaped text; no invented expiry or activation claim.
{{first_name}}$employee->first_nameRequired escaped employee first name, not the employer or staff sender.
{{company_name}}$payroll_settings->Company_nameRequired escaped employer display name, preserving capitalization in the actual source field. Not automatically the business.name used in headers.
{{employee_email}}$email, bound from $employee->emailRequired escaped payroll login identifier. Same recipient in the direct path; do not use the employer's email.
{{portal_password}}$password constructor argument -> password view bindingRequired original supplied value converted to string only for text output. Preserve leading zeros and all characters. This is not employee.password, which stores the bcrypt hash. Never insert a hash or regenerate a password in the view.
{{portal_url}}Existing literal https://payroll.built.africa/loginRequired validated complete HTTPS login destination. The button and visible fallback use this same value. No new reset/setup or token URL.

Source-only header value {{subject_business_name}} maps to the constructor business.name. It is not a required body token and is not currently passed in the Mailable's view-data array. It sets the existing subject pattern and business From display name; keep it separate from company_name.

Direct and bulk delivery

Content and workflow fidelity

Keep the greeting, employer registration context, complete email/password instructions and portal URL. Open payroll portal is a clearer primary action for the source's visible login URL. It opens login; it is not a signup, password reset, approval or payroll-payment action.

This body currently sends a password. The draft preserves that existing field as an explicit contract; it does not assert that it is temporary, one-use, expired after a period or subject to a mandatory first-login change. A setup-link alternative needs a separately authorized authentication workflow. Review this inherited password-delivery choice before production integration rather than silently dropping the access instruction or fabricating a setup endpoint.

States: direct registration with differing employer/business identities; bulk import using the same body; leading-zero synthetic string; and long values. Direct/bulk are delivery/data fixtures for one notification type, not separate template requirements. There are no optional blocks or supported blank-password states. Decide missing required values upstream; do not invent an employee identity or truncate the details.

Safe integration, images and text

ready/employee-welcome.html and ready/employee-welcome.txt are portable extracts. Every populated state has HTML/text under previews/. Portable {{placeholder_name}} syntax does not automatically reference Laravel variables. Prefer a dedicated full Blade HTML view with explicitly mapped existing values and a text() alternative in the existing Mailable. Do not nest a full document inside mail::message or introduce another templating framework.

Escape every text/attribute value. Preserve the supplied password literally as text after HTML escaping; do not trim it, turn it into a number, mask it, insert raw HTML or evaluate inserted token-looking text again. If string replacement is chosen, use one pass. Validate portal_url separately to the intended HTTPS payroll host/login path before attribute escaping it. The added fallback duplicates the same existing portal URL; there is no second legacy link field to reconcile.

Default logo: https://built-storage.ams3.cdn.digitaloceanspaces.com/Built/app_name.png. Retain assets/built-logo.png as the unchanged source. Use absolute HTTPS hosting or a real matching CID attachment and preserve proportions. Validate deployment overrides separately; remote images can be blocked. The logo's white backing supports the existing navy asset in dark mode.

No separate project-owned plain-text alternative was found for the source Markdown view; the supplied text is a proposed equivalent. No sample link logs in, resets a password or contacts a live employee. No production files, credential generation/storage, sender/queue/provider behavior or application actions are changed. Native dark CSS and browser checks do not establish Gmail, Outlook or iOS Mail compatibility. See employee-onboarding-batch.md and employee-onboarding-validation.md.