Files
app/docs/persimmons-038.md
T
2026-10-04 02:56:59 +00:00

4.4 KiB

Persimmons 0.3.8 acceptance

Architecture A: account → install extension → link/create encrypted vault → ready. The homepage presents only the current step. Installation instructions are in the product at /assets/install.html. “Linked” means the extension has validated the current account and host permission; locked/unlocked describes the separate memory-only key session. Merely detecting the extension never means linked. An unlocked empty vault explicitly says it is empty. A current installation has neither Get nor Update. Settings visibility is unchanged.

Why not B now: the server derives ciphertext ownership from its authenticated account cookie. The extension has a local, passphrase-wrapped encryption key, not a server-authenticated device identity. B requires a separately designed device registration and challenge/signature authentication protocol, server ownership bound to that identity, revocation, and an explicit authenticated account-linking transaction. Cross-profile use additionally requires an explicit wrapped-key transfer design. None of these are implemented by treating a local hint or key as server authority. This release adds no recovery or key sync.

Plain Enter submits the unlock form. A failed passphrase remains masked in the open popup for retry; successful unlock, locking, closing, or lost authentication clears it. The page receives only owner-validated connection/version and boolean initialized/unlocked/empty metadata, never item metadata, secrets, or key material. Existing origin checks, encryption, no-reveal, explicit save/fill, and timed memory-only sessions remain in force.

Single user retest script

  1. In a fresh Chromium profile, open https://persimmons.app and follow the one displayed next step: create account, install using the in-product instructions, then open 🍊, Link vault, allow Persimmons access, choose a vault passphrase, and press plain Enter. The popup says Unlocked and Your vault is empty.
  2. In Settings · Auto-lock, select After 15 minutes, then unlock with Enter. Close 🍊, wait 40 seconds, and reopen. It remains unlocked. Return to the homepage: it says Your vault is empty, with no Get, Update, or unlock prompt.
  3. On an allowed HTTPS login form (the disposable browser check uses https://wp.phly.cloud/wp-login.php), open 🍊 → Save for this site and save a disposable username/password. Select it and Fill: fields fill, without submitting. Delete it: the vault becomes empty again.
  4. Lock vault. Try a wrong passphrase with Enter: it remains masked in the field with a retry message. Enter the correct one: unlock succeeds. Sign out of Persimmons and reopen 🍊: it requires linking again and cannot fill.

Automation: node tests/persimmons-host-browser.cjs runs the same real Chromium popup interactions against disposable live accounts, including logout, account switch, host-permission revocation, and explicit contradictory-state assertions. Requires Playwright and its Chromium; PERSIMMONS_PLAYWRIGHT_MODULE and PERSIMMONS_CHROMIUM can select existing installations. PERSIMMONS_LOCAL_UI=1 uses candidate page assets with the real server transport before deployment. Generated screenshots contain no secret field values.

Candidate evidence — 2026-09-30

Canonical starting SHA: 97b445db4957d29f059c80f83d30af5da03a701d, fetched with ahead 0 / behind 0 and a clean worktree. No delegation. All eight extension Node test files passed. Eleven Python host, packaging, updater, ownership, encryption, and MCP no-reveal tests passed; the new install asset also passed host serving checks. A worker regression test proves that page status requests cannot cancel an in-progress unlock or lock another owner.

The final Chromium candidate run passed with a fresh profile, live authenticated server transport, candidate page assets, and the actual extension action popup. It asserted account → installation → linking, Enter unlock, retained wrong passphrase, save/fill/delete with no form submission, default-close locking, 15-minute policy surviving real popup destruction plus 40 seconds idle, unlocked-empty agreement between page and popup, absent Get/Update for the current build, logout denial, account-switch denial, and revoked-permission denial. Hero copy and the secondary 40px vault flow were checked in Chromium; the screenshot was visually reviewed with emoji fonts installed.