Raxx · internal docs

internal · gated ↑ index

FreeScout polish sprint — triage notes

Date: 2026-05-02 Cards: #712, #714, #718, #720 (refs #707) Author: sre-agent


Vault inventory (checked 2026-05-02)

Checked via heroku run --app raxx-console-prod pattern:

Secret Status
AWS_ACCESS_KEY_ID ABSENT
AWS_SECRET_ACCESS_KEY ABSENT
FREESCOUT_API_KEY ABSENT
POSTMARK_SERVER_API_KEY ABSENT

#714 — Daily backup: outstanding blocker

PR #746 merged 2026-04-30. Two backup tiers are documented and configured in principle:

Outstanding blocker: AWS credentials are absent from vault. The backup script on the instance cannot authenticate to S3 or call Lightsail APIs without one of:

What issue #714 still needs before it can be closed:

  1. Confirm Tier 1 snapshot is actually running — run this from a machine with AWS credentials: bash aws lightsail get-instance-snapshots --region us-east-1 \ --query 'instanceSnapshots[?contains(fromInstanceName, `raxx-tickets`)].[name,state,createdAt]' \ --output table Expected: at least one snapshot with state: available dated within the last 25 hours.

  2. Deploy scripts/ops/freescout-backup.sh to /usr/local/bin/freescout-backup.sh on the instance once IAM credentials are available: bash scp -i /tmp/lightsail_us_east_1.pem \ -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ scripts/ops/freescout-backup.sh \ admin@54.146.13.200:/tmp/freescout-backup.sh ssh -i /tmp/lightsail_us_east_1.pem \ -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ admin@54.146.13.200 \ "sudo mv /tmp/freescout-backup.sh /usr/local/bin/freescout-backup.sh && sudo chmod 750 /usr/local/bin/freescout-backup.sh"

  3. Add root cron entry on the instance: bash ssh -i /tmp/lightsail_us_east_1.pem \ -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ admin@54.146.13.200 \ "echo '30 7 * * * root /usr/local/bin/freescout-backup.sh' | sudo tee /etc/cron.d/freescout-backup"

IAM scope required for #744 (IAM user raxx-freescout-backup):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "LightsailSnapshot",
      "Effect": "Allow",
      "Action": [
        "lightsail:CreateInstanceSnapshot",
        "lightsail:GetInstanceSnapshot",
        "lightsail:GetInstanceSnapshots",
        "lightsail:DeleteInstanceSnapshot"
      ],
      "Resource": "*"
    },
    {
      "Sid": "S3BackupWrite",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:HeadObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::raxx-support-attachments",
        "arn:aws:s3:::raxx-support-attachments/db-backups/freescout/*"
      ]
    },
    {
      "Sid": "STSVerify",
      "Effect": "Allow",
      "Action": "sts:GetCallerIdentity",
      "Resource": "*"
    }
  ]
}

Once #744 lands and credentials are in Infisical at /MooseQuest/aws/freescout-backup/, wire them to the instance:

# On the raxx-tickets instance, add to /etc/environment or the cron environment:
AWS_ACCESS_KEY_ID="<value from vault>"
AWS_SECRET_ACCESS_KEY="<value from vault>"
AWS_REGION="us-east-1"

Issue #714 should remain OPEN until: Tier 1 snapshot is confirmed active AND Tier 2 cron is running on the instance.


#712 — Brand FreeScout outbound email templates

Status: BLOCKED — blocked label is correct. The card requires the UX designer branding spec before templates are finalized. No FreeScout API token is in vault, so API automation is not currently possible.

When this unblocks: When the ux-designer branding research task completes, the implementer (feature-developer) will need SSH access to the instance and/or FreeScout admin access. Until then, the steps below are the full implementation guide.

Context: How FreeScout email templates work

FreeScout uses Laravel Blade templates for outbound emails. Template files live at:

/var/www/html/freescout/resources/views/emails/

Key template files (verify on instance — paths may vary by FreeScout version):

Template File Sent when
New ticket (customer confirmation) customer/created.blade.php or similar Customer submits a new ticket
Operator reply customer/reply.blade.php or similar Operator sends a reply
Ticket closed customer/closed.blade.php or similar Ticket is marked resolved

FreeScout also ships a base email layout (typically layouts/email.blade.php or similar) that wraps all customer emails. Overriding the layout is the most durable approach — it applies to all email types at once.

Durability concern: Editing core template files directly will be overwritten on git pull / FreeScout update. The correct approach is to use a FreeScout theme or module. As of FreeScout 1.8.x, there is no official white-label email module for community edition. Check whether the Custom Emails module is available on the installed version. If not, use a local override approach described below.

Implementation steps (feature-developer, post-unblock)

Step 1: SSH to the instance

ssh -i /tmp/lightsail_us_east_1.pem \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  admin@54.146.13.200

Step 2: Identify the current email template structure

find /var/www/html/freescout/resources/views/emails -type f | sort
find /var/www/html/freescout/resources/views/layouts -type f | sort

Note the exact file names. FreeScout versions differ.

Step 3: Back up the original templates

sudo cp -r /var/www/html/freescout/resources/views/emails \
  /var/www/html/freescout/resources/views/emails.bak-$(date -u +%Y%m%d)

Step 4: Create the branded email layout

Replace the email layout (or the header partial — check which file controls the top of every email):

Branding values to apply (Confidence Engine palette, locked 2026-04-25):

Element Value
Background #f8f5f0 (snow)
Body text #0f172a (ink)
Accent / border #4a7c59 (moss)
Logo Raxx wordmark (see logo hosting note below)
Footer text Raxx Support | MooseQuest LLC. All rights reserved.
Footer email support@raxx.app
Font System stack: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif (no web fonts — deliverability)

Logo hosting note (critical for email): The logo URL in email templates must be publicly accessible without authentication. Do NOT use tickets.raxx.app (CF Access protected). Options:

  1. Host on the status-page CDN (e.g., https://status.raxx.app/raxx-wordmark.svg) if that domain is publicly accessible.
  2. Host on getraxx.com under a /assets/ path.
  3. Inline as base64 data URI in the template (most reliable, no external request, ~4 KB overhead for a simple SVG).

The canonical wordmark SVG is at docs/design/brand/logos/raxx-wordmark-c.svg in the repo.

Step 5: Footer exact string

<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
          font-size: 12px; color: #0f172a; margin: 0; padding: 16px 0;">
  Raxx Support | MooseQuest LLC. All rights reserved.
</p>

No FreeScout attribution. No "Powered by FreeScout" or equivalent.

Step 6: Test

  1. From FreeScout admin, open a test ticket and send an operator reply to kris@moosequest.net.
  2. Inspect the received HTML source. Verify: - Raxx wordmark renders (check network tab for image load). - Footer reads "Raxx Support | MooseQuest LLC. All rights reserved." - No "FreeScout" string in the HTML source (search with Ctrl+F in view-source). - Background color matches #f8f5f0.

Step 7: Clear FreeScout view cache

cd /var/www/html/freescout
sudo -u www-data /usr/bin/php artisan view:clear
sudo -u www-data /usr/bin/php artisan config:cache

Step 8: Document template file locations in runbook

Update docs/ops/runbooks/freescout.md with the exact file paths modified and whether the approach is durable across FreeScout updates.

FreeScout Settings > Mailboxes > Templates (UI path)

FreeScout also has a UI-based template system under Settings > Mailboxes > [mailbox name] > Auto Reply (and similar tabs). This controls text-only auto-response messages, not the full HTML email template. Check this UI after SSH template override to ensure the auto-reply text is also Raxx-branded.

Steps: 1. Log in to https://tickets.raxx.app. 2. Go to Settings (gear icon). 3. Click Mailboxes. 4. Click the mailbox name (e.g., support@raxx.app). 5. Review the Auto Reply, Satisfaction rating, and any other template tabs. 6. Replace any FreeScout branding in the text with Raxx copy.


#718 — TOTP enrollment

Documented in docs/ops/runbooks/freescout.md (section: Admin account security > TOTP two-factor authentication).

This is an operator-only action. Kristerpher must scan the QR code and store recovery codes. The runbook is the deliverable for this sprint; the actual enrollment is a follow-up operator action.


#720 — FreeScout company branding

Documented in docs/ops/runbooks/freescout.md (section: Branding and company settings).

Decision recorded: tickets.raxx.app/login is operator-only (behind CF Access). Minimal Raxx wordmark is appropriate. Full customer-facing branding is not required for this surface.

This is an operator action (~10 min). Click path is in the runbook.