docs: update passcode security status and add async $effect guard pattern

- TODO__Agents.md: check off completed passcode JWT migration items;
  document the three remaining cleanup steps (deferred ~a few days)
- PROJECT__AE_Site_Passcode_Security.md: update status to active/cleanup-deferred,
  check off completed implementation checklist items
- GUIDE__SvelteKit2_Svelte5_DexieJS.md: add new section documenting the
  async-function-from-$effect guard-reset infinite loop pattern, with the
  real example from the passcode auth bug (2026-06-18)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-06-18 13:32:50 -04:00
parent d939f3190d
commit 6222f7655d
3 changed files with 94 additions and 18 deletions

View File

@@ -65,12 +65,16 @@ Finalizing the 100% adoption of V3 Standard endpoints and retirement of legacy w
## 🚧 High Priority Workstreams
### [Security] Site Passcode JWT Migration
### [Security] Site Passcode JWT Migration — mostly complete (2026-06-18)
- [ ] **[Security] Verify `/authenticate_passcode` deployment** — confirm explicit role priority, complete role flags, `auth_type: 'passcode'`, per-role TTLs, and minimum length validation.
- [ ] **[Security] Replace local passcode comparison** — migrate `e_app_access_type.svelte` to server verification, JWT storage, and pending/error UI.
- [ ] **[Security] Remove client-side passcode delivery/storage** — stop caching `access_code_kv_json`, remove `site_access_code_kv` from auth state, and remove passcode logging.
- [ ] **[Security] Enforce passcode JWT expiry on restore** — expired passcode sessions must return to anonymous without affecting user-login JWT handling.
- [x] **[Security] Verify `/authenticate_passcode` deployment** — all four backend fixes confirmed: role priority, full role flags, `auth_type: 'passcode'`, per-role TTLs, `min_length=5`. Endpoint moved to `/v3/action/auth/authenticate_passcode`.
- [x] **[Security] Replace local passcode comparison** — `e_app_access_type.svelte` now POSTs to the API with debounce + Enter-key trigger, stores returned JWT, shows pending spinner and inline error. Local comparison kept as silent fallback (network error / ghost site_id). `USE_API_PASSCODE_AUTH = true`.
- [x] **[Security] Enforce passcode JWT expiry on restore** — `+layout.ts` decodes JWT on page load, resets to anonymous if expired. Only targets `auth_type: 'passcode'` JWTs; user-login JWTs unaffected.
- [ ] **[Security] Cleanup — remove client-side passcode delivery/storage** — intentionally deferred ~a few days while fallback is observed in production. Three steps when ready:
1. Comment out `ae_loc_init['site_access_code_kv'] = json_data.access_code_kv_json || {}` in `+layout.ts` (~line 394)
2. Remove `site_access_code_kv` from `AuthLocState` and `auth_loc_defaults` in `ae_stores__auth_loc_defaults.ts`
3. Remove passcode-map log from `handle_check_passcode_local()` in `e_app_access_type.svelte` (fires at `log_lvl > 1`)
4. Backend Phase 2 (separate): remove `access_code_kv_json` from `Site_Domain_Base` response model
Reference: `documentation/PROJECT__AE_Site_Passcode_Security.md`.