docs(email): record recovery evidence
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
Updated: 2026-08-10
|
||||
|
||||
- Progress report: `docs/verification/mail-001-job-email-hub.md`
|
||||
- Commands/results: `docs/audits/verification-log.md` V-126–V-135
|
||||
- Commands/results: `docs/audits/verification-log.md` V-126–V-136
|
||||
- Hub/legacy-route tests: `job-tracker-ui/src/correspondence-inbox-page.test.tsx`
|
||||
- Reused review decision tests: `job-tracker-ui/src/gmail-review-page.test.tsx`
|
||||
- Provider-neutral API tests: `JobTrackerApi.Tests/EmailControllerTests.cs`
|
||||
@@ -12,5 +12,6 @@ Updated: 2026-08-10
|
||||
- Delivery adapter tests: `JobTrackerApi.Tests/EmailProviderDeliveryTests.cs`
|
||||
- Explicit-send/tenant/idempotency tests: `JobTrackerApi.Tests/EmailSendControllerTests.cs`
|
||||
- Confirmed composer tests: `job-tracker-ui/src/correspondence-inbox-page.test.tsx`
|
||||
- Implementation commits: `6008b4a`, `536d403`, `a20775c`, `653f011`, `e9937ac`, `123fc55`, `449faeb`
|
||||
- Restart-recovery/two-owner tests: `JobTrackerApi.Tests/EmailSendAttemptStoreTests.cs`
|
||||
- Implementation commits: `6008b4a`, `536d403`, `a20775c`, `653f011`, `e9937ac`, `123fc55`, `449faeb`, `ee5ef7e`
|
||||
- Mocked provider data only; no real email, provider connection, private content, production service or external request was used.
|
||||
|
||||
@@ -167,3 +167,4 @@ Output was reduced to filenames and commit counts. The token artifact appears un
|
||||
| V-133 | Focused delivery/provider/controller tests; full backend; focused inbox Jest; frontend production build; `git diff --check` | Repository root / `job-tracker-ui` | Verify explicit consent scopes, capability reporting, Gmail/Graph payloads, IMAP read-only, rejected/reauth/uncertain classification and regressions | PASS — focused backend 18/18; full backend 613/613; inbox 5/5; production build and patch check pass | Ephemeral encrypted tokens, synthetic recipients/content and mocked HTTP only. No OAuth/provider/email call or real account. Browser/production not run | External provider/production limitation |
|
||||
| V-134 | Focused `EmailSendControllerTests|EmailSendAttemptStoreTests|EmailControllerTests`; full backend; staged diff/secret-name/whitespace review | Repository root | Verify explicit confirmation, bounded input, owner isolation, canonical idempotency, rate-limited provider admission, correspondence/audit transaction and failed/uncertain behavior | PASS — focused 12/12; full backend 619/619; no whitespace errors or secret values. Provider called once across duplicate requests; cross-tenant/unconfirmed/malformed requests never reserve or deliver | SQLite and fake provider only. No real provider/email/network/browser/production execution. Crash-abandoned `sending` reconciliation remains | External provider/runtime limitation |
|
||||
| V-135 | Focused correspondence-inbox Jest; full frontend Jest; `npm.cmd run build`; `git diff --check` | `job-tracker-ui` / repository root | Verify editable provider-bound reply, visible review fields, confirmation/cancel, one UUID, sent/uncertain duplicate safety, responsive TypeScript/build and regression hygiene | PASS — focused 7/7; full 49/49 suites and 190/190 tests; production build; no whitespace errors | JSDOM and mocked API/provider data only; no running browser/provider/email. Full Jest took 75.632s and retained the existing force-exit/open-handle notice | Browser/provider/production limitation |
|
||||
| V-136 | Focused `EmailSendAttemptStoreTests|EmailSendControllerTests`; full backend; provider-dependency search; `git diff --check` | Repository root | Verify restart recovery, stale/fresh boundary, pending-failed versus sending-uncertain classification, two-owner notification isolation, idempotency and absence of provider retries | PASS — focused 10/10; full backend 620/620; repeated recovery 0/0; each owner sees one content-free notification; recovery code has no provider/SMTP dependency; no whitespace errors | Real SQLite and manual clock; no process kill, MariaDB, provider, email or production runtime. Five-minute scan performance is unmeasured on a large ledger | Runtime/performance limitation |
|
||||
|
||||
@@ -69,9 +69,9 @@ Status: `IN PROGRESS`. Canonical hub routing, provider-neutral reads, explicit-c
|
||||
- Focused delivery/provider/capability: 18/18; send ledger: 3/3; provider/correspondence controllers: 5/5; hub detail: 5/5.
|
||||
- Explicit-send controller/store/read focused tests: 12/12.
|
||||
- Confirmed composer focused tests: 7/7.
|
||||
- Full backend: 619/619; full frontend: 49/49 suites, 190/190 tests.
|
||||
- Full backend: 620/620; full frontend: 49/49 suites, 190/190 tests.
|
||||
- Production build/TypeScript and `git diff --check`: pass.
|
||||
- Implementation commits: `6008b4a`, `536d403`, `a20775c`, `653f011`, `e9937ac`, `123fc55`, `449faeb`.
|
||||
- Implementation commits: `6008b4a`, `536d403`, `a20775c`, `653f011`, `e9937ac`, `123fc55`, `449faeb`, `ee5ef7e`.
|
||||
|
||||
## Implemented editable composer increment
|
||||
|
||||
@@ -82,13 +82,20 @@ Status: `IN PROGRESS`. Canonical hub routing, provider-neutral reads, explicit-c
|
||||
- A network/unknown server interruption is treated as uncertain on the client. Successful sends refresh the same correspondence domain; no second copy or autonomous AI/send path was added.
|
||||
- Draft state is in-memory for this increment. Navigation within the hub preserves it, but refresh persistence and compose-new-message flow remain separate work.
|
||||
|
||||
## Implemented interrupted-send recovery increment
|
||||
|
||||
- A safety worker starts only after database readiness and checks every five minutes. It has no email-provider, SMTP or message-content dependency.
|
||||
- Attempts still pending after 15 minutes are definitively failed as stopped before provider delivery. Attempts still sending after 15 minutes become uncertain; neither state is queued or retried.
|
||||
- Recovery uses conditional updates inside the local database transaction, so overlapping replicas can observe the same candidate but only one changes it and creates the notification.
|
||||
- Each affected owner receives one generic, content-free notification linked to Job email. The notification never contains provider, recipient, subject or body.
|
||||
- A real-SQLite two-owner clock/restart test proves stale/fresh separation, owner-visible notifications, repeat-run idempotency and no transition back to pending/sending.
|
||||
|
||||
## Remaining MAIL-001 work
|
||||
|
||||
- Extend shared provider-neutral thread navigation and application embedding while preserving provider capability differences.
|
||||
- Surface provider identity, reauthorization, read/unread, pin/read-later/archive/spam/trash only where the provider supports it.
|
||||
- Share thread detail and link/unlink actions between hub and job workspace.
|
||||
- Add durable draft/refresh recovery and compose-new-message behavior if confirmed by the remaining workflow inventory; replies are implemented.
|
||||
- Reconcile abandoned `sending` attempts to an explicit uncertain/manual-review state after process failure; never auto-resend them.
|
||||
- Include non-sensitive send-attempt metadata in user export and verify account/job deletion coverage before production rollout.
|
||||
- Preserve minimal audit metadata without sensitive body logging; verify Free non-AI access and Pro-only AI assistance.
|
||||
- Complete link/unlink/dismiss/draft/send/failure/two-user/application-embed tests plus browser/production provider gates. No real email may be sent during repository verification.
|
||||
@@ -99,4 +106,4 @@ The first focused Jest invocation exhibited the repository's open-handle delay.
|
||||
|
||||
## Rollback
|
||||
|
||||
Disable the UI/admission path before rollback. Revert `123fc55` to remove the send route, then `e9937ac` for send consent/adapters and `653f011` (after migration downgrade) for the ledger, followed by earlier read/routing commits. Existing provider grants are not revoked by a code rollback; disconnect/reconnect is an explicit user action.
|
||||
Revert `ee5ef7e` to stop recovery and `449faeb` to remove the composer, then disable admission. Revert `123fc55` to remove the send route, `e9937ac` for send consent/adapters and `653f011` (after migration downgrade) for the ledger, followed by earlier read/routing commits. Existing provider grants are not revoked by a code rollback; disconnect/reconnect is an explicit user action.
|
||||
|
||||
@@ -439,3 +439,13 @@
|
||||
- **Consequences:** read-only connections require explicit reconnect consent. This increment supports replies, not durable refresh recovery or a new-message composer; those remain tracked rather than being implied. Basic email remains ungated by Pro and no AI path can send.
|
||||
- **User approval required:** No; this is synthetic local MAIL-001 implementation. Real provider/email verification remains gated.
|
||||
- **Reversible:** Yes. Revert `449faeb`; API, ledger, scopes and saved correspondence remain unchanged.
|
||||
|
||||
## DEC-045 — Interrupted sends age to terminal safety states without retry
|
||||
|
||||
- **Date:** 2026-08-10
|
||||
- **Decision:** Run a post-readiness safety scan every five minutes. After 15 minutes, pending attempts become failed-before-provider and sending attempts become uncertain. Use conditional cross-owner updates in one local transaction and create one content-free owner notification; never invoke or enqueue provider delivery.
|
||||
- **Reason/evidence:** a process can stop between ledger reservation, provider acceptance and local completion. The application can prove an old pending attempt never reached the provider, but cannot prove the same for sending. Real-SQLite two-owner tests prove classification, fresh-row preservation, notification isolation and repeat-run idempotency.
|
||||
- **Alternatives considered:** retry on restart; leave rows indefinitely; mark every row failed; mark every row sent; scan provider mailboxes; add provider-specific reconciliation. These risk duplicate email, misleading state, excessive provider authority or unresolved user state.
|
||||
- **Consequences:** interrupted sending requires manual Sent-folder review. Multiple replicas may select the same candidate, but the status predicate allows only one update/notification. The five-minute query intentionally avoids a new migration in this increment; large-ledger performance remains a measured rollout check.
|
||||
- **User approval required:** No; this is local safety recovery with no provider/external call.
|
||||
- **Reversible:** Yes. Revert `ee5ef7e`; existing terminal states and notifications remain truthful and should not be rewritten.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
Updated: 2026-08-10
|
||||
|
||||
- **Overall programme status:** Active. Six packages are locally verified; nineteen packages through CAREER-002 are implemented with automated/runtime evidence but blocked from applicable browser/provider/production gates; MAIL-001 is in progress with seven implementation increments.
|
||||
- **Current work package:** `MAIL-001` — consolidated job-email hub and explicit sending (`IN PROGRESS`); routing/reads/detail, ledger, Gmail/Graph delivery/re-consent, tenant-safe send API and confirmed editable reply UI are committed. Abandoned-attempt reconciliation, legacy-send retirement and remaining hub actions remain.
|
||||
- **Overall programme status:** Active. Six packages are locally verified; nineteen packages through CAREER-002 are implemented with automated/runtime evidence but blocked from applicable browser/provider/production gates; MAIL-001 is in progress with eight implementation increments.
|
||||
- **Current work package:** `MAIL-001` — consolidated job-email hub and explicit sending (`IN PROGRESS`); routing/reads/detail, ledger, Gmail/Graph delivery/re-consent, safe send API/UI and cross-owner-safe interrupted-attempt recovery are committed. Legacy-send retirement and remaining hub actions remain.
|
||||
- **Completed work packages:** None are `DONE`; all repository security/AI packages still have applicable browser, provider and/or production gates.
|
||||
- **Locally verified work:** SEC-001, SEC-002, SEC-003, SEC-005A, CORE-001 and PROD-002 (`VERIFIED LOCALLY`).
|
||||
- **Implemented, verification incomplete:** SEC-004, SEC-005B, SEC-008, CORE-002, BG-001, OPS-001A/B/C, POL-001/002, AI-001/002/003/004, UX-001/002, QA-001, CAREER-001 and CAREER-002 (`IMPLEMENTED — NOT VERIFIED`). CAREER-002 now protects unsaved edits and provides tested structured custom-entry, profile-override and preview-error interactions; all automated/build gates pass.
|
||||
@@ -12,10 +12,10 @@ Updated: 2026-08-10
|
||||
- **Deferred work:** None. Conditional multi-replica coordination, model deletion, realtime operation delivery and unrelated production changes remain outside current packages.
|
||||
- **Next five work packages:** MAIL-001 consolidated email experience; JOBS-001 job-search/application redesign; HOME-001 homepage/Pro promotion; UX-003 authentication/profile polish; PRODUCT-001 homepage/Pro claims. SEC-006/007 resume after package-index permission.
|
||||
- **Status counts:** 6 `VERIFIED LOCALLY`; 19 `IMPLEMENTED — NOT VERIFIED`; 1 `IN PROGRESS`; 8 `NOT STARTED`; 5 `BLOCKED`; 0 `DONE`; 0 `DEFERRED`.
|
||||
- **Test status:** backend 619/619; frontend 49/49 suites and 190/190 tests; MAIL-001 composer 7/7, send/read/store focused 12/12, delivery/capability 18/18, provider/correspondence 5/5 and hub detail 5/5; migration rehearsal and production build pass. Jest open-handle/slow-run behavior is recorded in V-127/V-128/V-130/V-131/V-135.
|
||||
- **Test status:** backend 620/620; frontend 49/49 suites and 190/190 tests; MAIL-001 recovery/send focused 10/10, composer 7/7, delivery/capability 18/18, provider/correspondence 5/5 and hub detail 5/5; migration rehearsal and production build pass. Jest open-handle/slow-run behavior is recorded in V-127/V-128/V-130/V-131/V-135.
|
||||
- **Deployment status:** No deployment performed. No production migrations were run. AI operation worker remains disabled by default.
|
||||
- **Production status:** Unchanged and unverified. No provider/model call, model pull, external request or paid API occurred.
|
||||
- **Known regressions:** None found by automated suites. Jest still needs `--forceExit` and reports its existing open-handle notice. Email-provider/send tests are fake/local only; real delivery is not claimed. A process stop after ledger admission can leave `sending` for later reconciliation, but duplicate delivery remains fail-closed. Direct clean EF-only SQLite migration still hits the pre-existing historical blank-chain defect before later migrations; normal startup owns reconciliation. Cross-feature monthly AI usage accounting remains a rollout gap.
|
||||
- **Known regressions:** None found by automated suites. Jest still needs `--forceExit` and reports its existing open-handle notice. Email-provider/send tests are fake/local only; real delivery is not claimed. Interrupted attempts are aged after 15 minutes and notified without retry; the five-minute scan is unmeasured on a large ledger. Direct clean EF-only SQLite migration still hits the pre-existing historical blank-chain defect before later migrations; normal startup owns reconciliation. Cross-feature monthly AI usage accounting remains a rollout gap.
|
||||
- **Outstanding security findings:** JT-001 repository ownership remains High deployment risk until migration/inventory/provider checks; production portion of JT-002; JT-006/JT-009 and associated JT-011/JT-012/JT-022 prerequisites. JT-005 foundations are implemented; AI worker activation awaits controlled rollout. JT-007/JT-008/JT-010 lack browser/provider/production verification.
|
||||
|
||||
## Current evidence
|
||||
|
||||
@@ -651,9 +651,9 @@ Ordering differences from the suggested list:
|
||||
- **Required production verification:** provider read/draft/send requires explicit authorized synthetic account; never real unsolicited email.
|
||||
- **Status:** `IN PROGRESS`.
|
||||
- **Blocker:** real provider verification external; mocked/local implementation not blocked after dependencies.
|
||||
- **Evidence:** `docs/verification/mail-001-job-email-hub.md`; V-126–V-135. Composer 7/7; send/read/store focused 12/12; delivery/capability 18/18; provider/correspondence 5/5; hub detail 5/5; backend 619/619; frontend 49/49 suites and 190/190 tests plus build.
|
||||
- **Commit:** `6008b4a` (hub), `536d403` (neutral reads), `a20775c` (safe detail), `653f011` (ledger), `e9937ac` (Gmail/Graph delivery adapters and consent), `123fc55` (explicit-confirmed send API), `449faeb` (confirmed reply composer).
|
||||
- **Remaining work:** abandoned-sending reconciliation; legacy follow-up SMTP retirement; export/deletion coverage; durable/new-message drafts; shared thread/application actions and category capabilities; free/pro and browser/production verification. Existing connections need explicit re-consent; IMAP remains read-only. No real email; uncertain sends need manual reconciliation.
|
||||
- **Evidence:** `docs/verification/mail-001-job-email-hub.md`; V-126–V-136. Recovery/send focused 10/10; composer 7/7; delivery/capability 18/18; provider/correspondence 5/5; hub detail 5/5; backend 620/620; frontend 49/49 suites and 190/190 tests plus build.
|
||||
- **Commit:** `6008b4a` (hub), `536d403` (neutral reads), `a20775c` (safe detail), `653f011` (ledger), `e9937ac` (Gmail/Graph delivery adapters and consent), `123fc55` (explicit-confirmed send API), `449faeb` (confirmed reply composer), `ee5ef7e` (interrupted-send recovery).
|
||||
- **Remaining work:** legacy follow-up SMTP retirement; export/deletion coverage; durable/new-message drafts; shared thread/application actions and category capabilities; free/pro and browser/production verification. Existing connections need explicit re-consent; IMAP remains read-only. No real email; uncertain sends need manual reconciliation.
|
||||
|
||||
### JOBS-001 — Job-search source and assessment redesign
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
Updated: 2026-08-10
|
||||
|
||||
- **Exact current task:** MAIL-001 — reconcile crash-abandoned sending attempts without redelivery, then retire or route the legacy follow-up SMTP boundary through the safe provider-send path.
|
||||
- **Last completed step:** the provider-bound editable reply composer and app-owned confirmation flow were committed as `449faeb`; cancellation preserves the draft, one UUID is used per attempt, and uncertain results cannot retry.
|
||||
- **Exact current task:** MAIL-001 — retire or route the legacy follow-up SMTP boundary through the safe provider-send path without breaking draft generation or reminders.
|
||||
- **Last completed step:** five-minute post-readiness recovery was committed as `ee5ef7e`; attempts older than 15 minutes become failed-before-delivery or uncertain, each owner receives one content-free notification, and no provider retry occurs.
|
||||
- **Files currently modified:** MAIL-001 verification/log/master tracking documents only. Application code/tests are committed.
|
||||
- **Commands already run:** complete provider/send trace; read/detail/ledger/delivery/send/composer focused tests; full backend/frontend; TypeScript build; EF provider migration rehearsal; seven implementation commits. See V-126–V-135.
|
||||
- **Test results:** MAIL-001 composer 7/7, send/read/store 12/12, delivery/capability 18/18, provider/correspondence 5/5, hub detail 5/5; backend 619/619; frontend 49/49 suites and 190/190 tests; migration/model/build gates pass.
|
||||
- **Commands already run:** complete provider/send trace; read/detail/ledger/delivery/send/composer/recovery focused tests; full backend/frontend; TypeScript build; EF provider migration rehearsal; eight implementation commits. See V-126–V-136.
|
||||
- **Test results:** MAIL-001 recovery/send 10/10, composer 7/7, delivery/capability 18/18, provider/correspondence 5/5, hub detail 5/5; backend 620/620; frontend 49/49 suites and 190/190 tests; migration/model/build gates pass.
|
||||
- **Services currently running:** none started intentionally. Exact task-owned hung Jest/build Node processes were stopped; Codex browser runtimes were not touched. Pre-existing Docker services were not changed.
|
||||
- **Temporary files or processes:** none. No provider account, private email, external model, paid service or production service was accessed.
|
||||
- **Production changes currently active:** none. No deployment, migration, provider connection/sync/send or production payload occurred.
|
||||
- **Rollback status:** revert `449faeb` to remove the composer, keep admission disabled, then revert `123fc55` and `e9937ac`; downgrade `20260809195014_AddEmailSendAttempts` before reverting `653f011`. No production migration/deploy/provider grant occurred.
|
||||
- **Rollback status:** revert `ee5ef7e` to stop recovery, then `449faeb` to remove the composer; keep admission disabled before reverting `123fc55`/`e9937ac` and downgrade the ledger before reverting `653f011`. No production migration/deploy/provider grant occurred.
|
||||
- **Uncommitted changes:** MAIL-001 evidence/tracking documents only; commit/push before the next application increment.
|
||||
- **Known failures:** abandoned `sending` reconciliation, durable/new-message drafts, export coverage, full thread/category actions and non-Gmail review remain; existing accounts need re-consent and IMAP stays read-only. Legacy follow-up SMTP bypasses the new boundary. Browser/provider/MariaDB/production unavailable or unverified; Jest open handles; SEC-006 needs internet/package-index permission; parser isolation remains SEC-007.
|
||||
- **Exact next action:** commit/push this evidence, then add a bounded stale-attempt reconciliation path that marks old `sending` attempts uncertain without provider I/O or retry, with restart/tenant tests and operator-visible status.
|
||||
- **Known failures:** durable/new-message drafts, export coverage, full thread/category actions and non-Gmail review remain; existing accounts need re-consent and IMAP stays read-only. Legacy follow-up SMTP bypasses the new boundary. Browser/provider/MariaDB/production unavailable or unverified; recovery scan performance is unmeasured at large ledger scale; Jest open handles; SEC-006 needs internet/package-index permission; parser isolation remains SEC-007.
|
||||
- **Exact next action:** commit/push this evidence, then trace every `SendFollowUp` caller and split draft generation/reminder behavior from delivery; disable or route any user-facing SMTP delivery through the explicit-confirmed provider boundary without changing scheduled notification email.
|
||||
- **Work that can continue independently:** remaining MAIL-001 repository work and later UX packages. SEC-006/007 await package-index permission; PROD-001/003/004 await production access.
|
||||
- **Decisions still required from the user:** none for synthetic/code-inspected repository work. Any provider connection or send test, internet/package upgrades, private data, external/paid providers and production actions retain explicit approval/safety gates; SEC-009 retention/legal policy remains unresolved.
|
||||
|
||||
Reference in New Issue
Block a user