Skip to content

Staging manual-test checklist — 2026-05-07 deploy cycle #48

@dobby-coder

Description

@dobby-coder

Staging manual-test checklist — 2026-05-07 deployment cycle

This issue collects the manual verification steps for the changes shipping in this cycle. Items are grouped by surface area and reference the underlying PR. Run these against the staging environment once everything is deployed.

Trigger: encryption4all/postguard-js#47

Skip the items that have already been verified in PR test plans. The lists below focus on end-to-end behaviour against staging — things that cannot be covered by unit tests alone.


1. Upload robustness — retry + idempotency

PRs: encryption4all/postguard-js#47, encryption4all/cryptify#144, encryption4all/cryptify#145

Setup: open the staging Business UI, log in, start a flow that uploads a multi-chunk file (≥ ~20 MB so several chunks fly).

  • Happy path — upload a file on a healthy network, confirm it completes and the recipient can decrypt + download.
  • Slow network retry — DevTools → Network → throttle to "Slow 3G", upload again, confirm transparent completion (any in-flight retries should be invisible to the user; the onRetry UI hint may show "retrying… attempt N of M").
  • Server flap mid-chunk — start an upload, kill the cryptify container after the first chunk has been ACK'd but before the next, restart cryptify within the retry budget. Expected: upload completes, the recipient receives the same file (sha256 unchanged).
  • Server hard-down — stop cryptify entirely, attempt an upload. Expected: SDK retries maxAttempts then surfaces a clear error (no infinite spinner).
  • Session expired — start an upload, restart cryptify (clears in-memory state), push the next chunk. Expected: upload aborts with an "upload session expired" type error, not a generic network error, and the SDK does not burn its retry budget on it.
  • Custom session TTL (only if staging cryptify config sets session_ttl_secs to a low value): leave a partially-uploaded file idle past the TTL → next chunk gets the structured 404 (reason: expired_or_unknown).
  • Quota / 413 — attempt an upload that exceeds the per-upload limit. Expected: immediate error, no retry storm.
  • User-cancelled upload — start an upload then cancel from the UI. Expected: aborts cleanly, no retries.
  • Recipient download — open the recipient link from one of the above successful uploads on a slow connection, confirm the download retries on transient failures and the resulting file matches sha256.

2. Cryptify API-key tier (bearer auth)

PRs: encryption4all/postguard#167, encryption4all/cryptify#139, encryption4all/postguard-js#43

  • PKG validate endpoint reachablecurl -H 'Authorization: Bearer PG-<real-key>' https://<staging-pkg>/v2/api-key/validate returns 200 with {tenant_id, organisation_name}. Bogus key → 401. No header → 404.
  • Tier upgrade path — using the Business UI logged in as a tenant whose tier requires the API key, send an encrypted email with a large attachment (> 5 GB if feasible, otherwise sanity-check via cryptify logs that the tier was upgraded). Expected: upload accepted at the higher tier.
  • Default tier degrade — send an encrypted email without an API key (or with an unknown one). Expected: silent degrade to 5 GB tier; ≤ 5 GB upload still works.
  • PKG unreachable + large upload — temporarily firewall PKG from cryptify and retry a > 5 GB upload. Expected: cryptify returns 503, SDK surfaces a network error. Restore PKG and confirm recovery.
  • /v2/sign/key regression check — verify the existing pg.sign.apiKey('PG-…') signing path still works for normal tier-1 sends (no regression from the validate-endpoint plumbing).

3. PKG hardening

PRs: encryption4all/postguard#160, encryption4all/postguard#161, encryption4all/postguard#164, encryption4all/postguard#162

  • JSON body limitcurl -X POST -H 'Content-Type: application/json' --data-binary @<128KB-file>.json https://<staging-pkg>/<endpoint> should be rejected (was 4 MiB, now 64 KiB).
  • Missing key file — start a PKG instance pointing at a non-existent key file path. Expected: clean error message in logs, no panic / stack trace.
  • CLI smoke — run pg-cli against staging with an intentionally bad flag (e.g. unparseable URL); expect a friendly error, not a panic.

4. Business app — locale, sessions, CSP

PRs: encryption4all/postguard-business#40, encryption4all/postguard-business#42, encryption4all/postguard-business#41

  • Dutch locale (clean) — in a private window, set browser language to Dutch (nl-NL), load staging. Expected: UI is in Dutch.
  • English locale (clean) — in a private window, set browser language to English. Expected: UI is in English.
  • Locale fallback — set browser language to de-DE. Expected: UI falls back to English (not blank, not throw).
  • Concurrent locale isolation — open two private windows simultaneously, one with NL, one with EN, click around in both. Expected: neither window's UI flips to the other's language (was the race fixed in fix: stop mutating global svelte-i18n locale store from server hook #40).
  • Session activity throttle — log in, then watch the DB / network: rapid clicks within a 5-min window should not generate an UPDATE sessions SET last_active_at per request. After 5+ min idle and one new request, the UPDATE should fire once.
  • CSP Report-Only — load the Business app, open DevTools → Console. Expected: any CSP violations are logged in report-only mode (the page still renders normally — nothing should be blocked). POST /api/csp-report should receive entries (check server logs).
  • CSP nonce sanity — view-source and confirm SvelteKit's inline boot script has a nonce= attribute set; styles render correctly (no FOUC).
  • Particular flows under CSP — exercise the Yivi proxy / /irma flow, the iconify SVG icons, and any third-party-styled component. Watch for unexpected violation reports — they're not blockers but worth listing for the next tightening pass.

5. Outlook add-in

PRs: encryption4all/postguard-outlook-addon#29, encryption4all/postguard-outlook-addon#31, encryption4all/postguard-outlook-addon#34, encryption4all/postguard-outlook-addon#35

Sideload the staging manifest in each client. For each platform, the goal is "send an encrypted email and have the recipient decrypt it":

  • Outlook on the web (Chrome) — one-click Encrypt & Send works, Yivi dialog opens without a popup prompt.
  • Outlook on the web (Safari, fresh profile / no popup permission) — first attempt: Office popup prompt appears, click Allow → dialog opens → inline Safari hint visible (<aside id="pg-dlg-safari-tip">) pointing at Settings → Websites → Pop-ups.
  • Outlook on the web (Safari, popup permission already granted) — one-click again, no prompt.
  • Outlook for Mac (native) — clicking Send shows the Smart Alert instructing the user to use the taskpane "Encrypt & Send" button. Use the taskpane button → encryption completes.
  • Outlook for Windows (native) — one-click Encrypt & Send works.
  • Keyboard a11y / focus visibility — Tab through the taskpane: every interactive element (buttons, encrypt toggle, attribute inputs, delete-attribute, add-attribute chips) should show a 2px dark-blue focus outline. Press Enter on a focused button: visible :active feedback.
  • Decrypt — on each platform, open an encrypted email sent from another platform → decrypt flow works.

6. Thunderbird add-in

PRs: encryption4all/postguard-tb-addon#90

  • XPI install — install the latest XPI (downloaded from postguard.eu — see §7) into a fresh TB profile. Expect no manifest/permission errors.
  • Send encrypted — compose, encrypt, send. Recipient on a different client (Outlook web, JS SDK, or another TB) decrypts successfully.
  • Decrypt tier-3 envelope — decrypt an email originally sent via the Outlook add-in (tier-3) — confirms the isPGEncrypted recognition path still works after the dependency bumps.

7. postguard.eu — addon distribution

PRs: encryption4all/postguard-website#141, encryption4all/postguard-website#143

  • Asset HEAD checks
    • curl -I https://postguard.eu/downloads/postguard-tb-addon.xpi → 200, content-type application/x-xpinstall (or application/zip — note actual), expected size matching the seeded version.
    • curl -I https://postguard.eu/downloads/postguard-outlook-manifest.xml → 200, content-type application/xml.
  • Sha256 verify — download both files, run sha256sum, compare against the cached sibling .json metadata files in the deployed image.
  • /addons page — Thunderbird tab — clicking the install link triggers an immediate XPI download (no GitHub redirect).
  • /addons page — Outlook tab — the "Add custom add-in" URL points at https://postguard.eu/downloads/postguard-outlook-manifest.xml, not the old irmaseal.z6.web.core.windows.net URL. Add the URL via OWA → My add-ins → Add a custom add-in → Add from URL — manifest validates, add-in installs.
  • Sync workflow — manually trigger the Sync addons workflow via workflow_dispatch. With current upstream releases, expect a no-op run. Then bump or remove a metadata .json and re-run → expect a chore PR opened by peter-evans/create-pull-request.
  • Wide-logo assets — the new wide PostGuard logo renders correctly across breakpoints on / and /addons (no clipping, no aspect-ratio distortion).

8. postguard.eu — blog RSS feed

PR: encryption4all/postguard-website#149

  • Feed reachablecurl -I https://postguard.eu/blog/rss.xml → 200, content-type application/xml or application/rss+xml (note the actual value).
  • Feed validates — paste the deployed feed URL into https://validator.w3.org/feed/ → no errors (advisory warnings about optional elements are acceptable).
  • Autodiscovery <link> — view-source on https://postguard.eu/blog and confirm <link rel="alternate" type="application/rss+xml" href=".../blog/rss.xml"> is present in <head>.
  • RSS reader subscribe — point an RSS reader (NetNewsWire / Feedly / Thunderbird) at https://postguard.eu/blog and confirm it auto-discovers the feed and subscribes without manual URL entry.
  • Item content — in the reader, each post shows the correct title, description, publish date, and author from the .svx frontmatter; XML-special characters (&, <, >, quotes) in any post render correctly (no double-escaping, no broken markup).
  • Ordering — feed lists items newest-first; lastBuildDate matches the most recent post's date.
  • RSS button on /blog — the RSS button next to the blog heading is visible, keyboard-focusable (2px focus outline), and the link target resolves to /blog/rss.xml.
  • Prerendered output — the feed is served as a static asset (no SSR latency); a second curl should hit cache / show identical bytes.

9. Docs site

PR: encryption4all/postguard-docs#59

  • Sidebarpg-components no longer appears in any sidebar group on https://docs.postguard.eu/.
  • Overview / SDK index — confirm no broken links pointing to removed pg-components pages.
  • Search — search for "pg-components" → no live results (cached results may persist briefly).

10. Dependency updates — smoke pass

PRs: encryption4all/postguard-business#47, encryption4all/postguard#172, encryption4all/cryptify#143, encryption4all/cryptify#141, encryption4all/postguard-js#46, encryption4all/postguard-tb-addon#90, encryption4all/postguard-outlook-addon#34, encryption4all/postguard-website#143, encryption4all/ibe#26

  • Each service starts cleanly on staging — no dependency-resolution errors in startup logs for: PKG, cryptify, Business app, postguard.eu, docs.
  • End-to-end smoke — one full encrypted email sent from Business UI → received in TB add-in → decrypted. This is the catch-all for any silent dep regression.

11. Earlier-week regressions that may also reach staging

If staging is being refreshed from main rather than a specific tag, also re-verify items from earlier in the week that were merged but may not yet have been exercised on staging:


How to use this list

  • Tick items as you go on staging.
  • If something fails, open a follow-up issue / PR rather than annotating this checklist with prose.
  • Items that genuinely cannot be exercised on the current staging config: leave unchecked and add a one-line note.
  • Re-running this list against the next staging refresh is supported — copy the unchecked items into a new comment.

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions