feat: add standalone form page, close all audit gaps, pass v1.0 milestone

Add standalone form page template that bypasses the theme, with admin
setting and auto-creation on plugin activation. Fix reCAPTCHA v3 double
submission, remove jQuery dependency, extend localized JS strings, and
overhaul form CSS/JS. Update milestone audit to PASSED (9/9, 10/10, 5/5).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 12:08:52 +09:00
parent a9b1f2eb40
commit c0021befe2
14 changed files with 2382 additions and 1393 deletions

View File

@@ -1,27 +1,19 @@
---
milestone: "1.0"
audited: 2026-02-06
status: gaps_found
audited: 2026-02-07
status: passed
scores:
requirements: 8/9
phases: 7/7
integration: 8/10
flows: 3/3
requirements: 9/9
phases: 9/9
integration: 10/10
flows: 5/5
gaps:
requirements:
- "REQ-7: i18n support — German-only implemented, no .pot/.po files, no gettext functions, no English translation"
integration:
- "Session ID bug: session_id() used without session_start() for error transient keys — may cause error messages to display to wrong user or not display at all"
- "Additional work sections (Montage, Schrank, Elektriker, Dubelarbeiten, Packarbeiten, Anfahrt) extracted in Phase 2 but never integrated into form, email, or validation"
- "Sonstiges free text section not implemented"
requirements: []
integration: []
flows: []
tech_debt:
- phase: "02-legacy-data"
items:
- "get_additional_work() method is orphaned — data extracted but never consumed"
- phase: "06-email"
items:
- "session_id() for transient keys may not work in all hosting environments"
- "No admin resend email feature (documented as future)"
- "No email queue/retry mechanism"
- phase: "07-captcha"
@@ -32,9 +24,10 @@ tech_debt:
# Milestone Audit: v1.0 MVP
**Audited:** 2026-02-06
**Status:** GAPS FOUND
**Auditor:** gsd-integration-checker
**Audited:** 2026-02-07
**Status:** PASSED
**Auditor:** gsd-integration-checker + manual verification
**Previous Audit:** 2026-02-06 (gaps_found — all gaps now closed by Phases 8-9)
## Requirements Coverage
@@ -42,125 +35,118 @@ tech_debt:
|---|------------|--------|-------|-------|
| 1 | Plugin infrastructure with CPT `umzugsliste_entry` | SATISFIED | 1 | CPT registered, admin menu working |
| 2 | Settings page (email, captcha, thank you URL) | SATISFIED | 3 | WordPress Settings API, all 4 captcha options |
| 3 | Shortcode `[umzugsliste]` renders form matching legacy | SATISFIED | 4 | 7 rooms, 118 furniture items rendered |
| 3 | Shortcode `[umzugsliste]` renders form matching legacy | SATISFIED | 4, 8 | 7 rooms, 118 furniture items, 6 additional work sections, Sonstiges |
| 4 | Volume calculations matching legacy logic exactly | SATISFIED | 5 | Real-time JS with German decimal formatting |
| 5 | Captcha integration (all three providers) | SATISFIED | 7 | reCAPTCHA v2, v3, hCaptcha all implemented |
| 6 | Legacy HTML table email format generation | SATISFIED | 6 | HTML tables with bgcolor, legacy structure |
| 7 | i18n support (German primary, English secondary) | **NOT SATISFIED** | | No gettext functions, no .pot/.po files, German-only |
| 6 | Legacy HTML table email format generation | SATISFIED | 6, 8 | HTML tables with bgcolor, legacy structure, additional work + Sonstiges included |
| 7 | i18n support (German primary, English secondary) | SATISFIED | 9 | 222+ gettext-wrapped strings, POT/PO/MO files, email locale forcing |
| 8 | Form submission saves to CPT before email | SATISFIED | 6 | CPT save → email send order verified |
| 9 | Inline form validation (not JS alerts) | SATISFIED | 7 | Client-side + server-side, no alerts |
**Score: 8/9 requirements satisfied**
**Score: 9/9 requirements satisfied**
## Phase Completion
| Phase | Status | SUMMARY.md | Plans |
|-------|--------|-----------|-------|
| 1. Foundation | Complete | Yes | 1/1 |
| 2. Legacy Data Extraction | Complete | Yes | 1/1 |
| 3. Settings System | Complete | Yes | 1/1 |
| 4. Form Rendering | Complete | Yes | 1/1 |
| 5. Volume Calculations | Complete | Yes | 1/1 |
| 6. Email System | Complete | Yes | 1/1 |
| 7. Captcha & Validation | Complete | Yes | 1/1 |
| Phase | Status | SUMMARY.md | VERIFICATION.md | Plans |
|-------|--------|-----------|-----------------|-------|
| 1. Foundation | Complete | Yes | No (early phase) | 1/1 |
| 2. Legacy Data Extraction | Complete | Yes | No (early phase) | 1/1 |
| 3. Settings System | Complete | Yes | No (early phase) | 1/1 |
| 4. Form Rendering | Complete | No | No (early phase) | 1/1 |
| 5. Volume Calculations | Complete | No | No (early phase) | 1/1 |
| 6. Email System | Complete | No | No (early phase) | 1/1 |
| 7. Captcha & Validation | Complete | No | No (early phase) | 1/1 |
| 8. Bug Fixes & Legacy Parity | Complete | Yes (2) | Yes (gaps_found → fixed) | 2/2 |
| 9. Internationalization | Complete | Yes (2) | Yes (gaps_found → fixed) | 2/2 |
**Score: 7/7 phases complete**
**Score: 9/9 phases complete**
**Note:** Phases 1-7 were completed before verifier was introduced. Phases 8-9 have full VERIFICATION.md reports. Both verifications found gaps that were subsequently fixed:
- Phase 8: Missing `.small-1` and `.small-8` CSS column definitions → fixed in commit `8989d20`
- Phase 9: Hardcoded German strings in wp_die error page → fixed in commit `a7c7003`
## Cross-Phase Integration
### Integration Score: 10/10
**Connected exports:** 15 major class methods properly wired across phases
**Orphaned exports:** 0
**Missing connections:** 0
**Broken flows:** 0
### Verified Connections
- Phase 1 → All: Plugin bootstrap, CPT, constants properly consumed
- Phase 2 → Phase 4: `get_rooms()` and `get_furniture_items()` used in form renderer
- Phase 2 → Phase 5: CBM values passed via data attributes, JS reads correctly
- Phase 2 → Phase 6: Email generator uses furniture data to build HTML tables
- Phase 3 → Phase 6: Receiver email and thank you URL used in form handler
- Phase 3 → Phase 7: Captcha provider and keys used for widget/verification
- Phase 4 → Phase 5: Data attributes and DOM structure consumed by JS calculations
- Phase 4 → Phase 6: Field names match expected POST format in form handler
- Phase 4 → Phase 7: Error display and captcha widget integrated in form
- Phase 6 → Phase 1: CPT entries created with proper meta data
- Phase 7 → Phase 6: Captcha verification runs before form processing
### Integration Score: 8/10
| From | To | Via | Status |
|------|----|-----|--------|
| Phase 1 (Bootstrap) | All phases | `load_dependencies()` in umzugsliste.php | WIRED |
| Phase 2 (Furniture Data) | Phase 4, 6, 8 | `get_rooms()`, `get_furniture_items()`, `get_additional_work()` | WIRED |
| Phase 3 (Settings) | Phase 6, 7 | `get_option()` for email, captcha, thank you URL | WIRED |
| Phase 4 (Form Renderer) | Phase 5 (JS) | HTML data attributes (`data-room`, `data-cbm`, `.quantity-input`) | WIRED |
| Phase 4 (Shortcode) | Phase 5 (JS) | `wp_enqueue_script()` with jQuery dependency | WIRED |
| Phase 6 (Email Generator) | Phase 2 | `get_rooms()`, `get_additional_work()` for structure | WIRED |
| Phase 7 (Captcha) | Phase 4, 6 | `render_widget()` in form, `verify_response()` in handler | WIRED |
| Phase 8 (Form ID) | Phase 4, 6 | Hidden field → POST → transient → GET → display → delete | WIRED |
| Phase 8 (Additional Work) | Phase 2, 4, 6 | Data → form render → handler sanitize → email generate | WIRED |
| Phase 9 (i18n) | All display | `__()`, `esc_html__()` throughout, `wp_localize_script()` for JS | WIRED |
| Phase 9 (Email Locale) | Phase 6 | `switch_to_locale('de_DE')` before email, `restore_previous_locale()` after | WIRED |
## E2E Flow Verification
### Flow 1: Happy Path (Form → Email → Redirect)
**Status: COMPLETE**
Load form → fill data → real-time calculations → submit → nonce check → captcha check → validation → sanitize → save CPT → generate email → send via wp_mail → redirect to thank you page
### Flow 1: Form Display — COMPLETE
User visits page → shortcode registered → assets enqueued (CSS + JS + localized strings) → form renderer generates 7 rooms + additional work + Sonstiges + customer info + captcha → JavaScript initializes calculations
### Flow 2: Validation Error Path
**Status: COMPLETE (with session bug)**
Submit invalid → client validation blocks OR server validation catches → error transient → redirect back → display errors inline
**Bug:** `session_id()` used without `session_start()` — transient key may be empty
### Flow 2: Successful Submission — COMPLETE
Submit form → nonce verify → captcha verify → field validation → data sanitization → save CPT → switch locale to German → generate email HTML → wp_mail() → restore locale → redirect to thank you URL
### Flow 3: Admin View Submissions
**Status: COMPLETE**
Navigate to Umzugsliste → Eintraege → view CPT list → click entry → see JSON data and meta
### Flow 3: Validation Error — COMPLETE
Submit invalid form → errors collected → stored in transient with unique form_id → redirect with form_id parameter → renderer retrieves transient → errors displayed inline → transient deleted
**Flows Score: 3/3 flows functional**
### Flow 4: Admin Management — COMPLETE
Admin menu registered → CPT entries visible → settings page accessible → settings saved via WordPress Settings API
## Critical Gaps
### Flow 5: Translation — COMPLETE
Site locale set → text domain loaded on init → form UI in locale language → JS validation messages localized → email forced to German via locale switch → locale restored after email
### 1. i18n Not Implemented (Requirement 7)
- No `__()` or `_e()` gettext function calls anywhere
- No `.pot`, `.po`, or `.mo` translation files
- No `languages/` directory
- Text domain declared but never loaded (`load_plugin_textdomain()` missing)
- All user-facing strings hardcoded in German
- **Decision needed:** Is English support required for v1.0?
**Flows Score: 5/5 complete**
### 2. Session ID Bug
- `session_id()` returns empty string when PHP session not started
- Used in form-handler.php (lines 72, 82) and form-renderer.php (line 49)
- Transient key degrades to `umzugsliste_errors_default`
- In multi-user scenarios, errors could cross-contaminate between users
- **Fix required before production**
## Previous Gaps — All Closed
### 3. Additional Work Sections Orphaned
- Phase 2 extracted 32 fields across 6 sections (Montage, Schrank, Elektriker, Dubelarbeiten, Packarbeiten, Anfahrt)
- `get_additional_work()` method exists but is never called
- Not rendered in form, not included in email, not validated
- **Decision needed:** Required for v1.0 or defer to v1.1?
### 4. Sonstiges Free Text Missing
- Legacy form had a free text "Sonstiges" section
- Not implemented in any phase
- **Decision needed:** Required for v1.0 or defer?
## Tech Debt
| Phase | Item | Priority |
|-------|------|----------|
| 06 | session_id() without session_start() | Critical |
| 02 | get_additional_work() orphaned | High |
| 06 | No admin resend email | Low |
| 06 | No email queue/retry | Low |
| 07 | reCAPTCHA v3 no non-JS fallback | Low |
| 07 | Simple email regex validation | Low |
| Gap | Found In | Fixed By | Commit |
|-----|----------|----------|--------|
| i18n not implemented (REQ-7) | v1.0 audit (2026-02-06) | Phase 9 | `8751eac`..`a7c7003` |
| session_id() bug | v1.0 audit (2026-02-06) | Phase 8, Plan 01 | `28fcfcc` |
| Additional work sections orphaned | v1.0 audit (2026-02-06) | Phase 8, Plan 02 | `d0edef9`, `270349b` |
| Sonstiges free text missing | v1.0 audit (2026-02-06) | Phase 8, Plan 02 | `d0edef9` |
| Missing CSS .small-1/.small-8 | Phase 8 verification | Post-verification fix | `8989d20` |
| wp_die hardcoded German strings | Phase 9 verification | Post-verification fix | `a7c7003` |
## Security Verification
- Nonce protection: IMPLEMENTED
- Data sanitization: IMPLEMENTED
- SQL injection protection: SAFE (WordPress APIs)
- XSS protection: IMPLEMENTED (esc_html, esc_attr)
- CSRF protection: IMPLEMENTED (nonce + referer check)
- Data sanitization: IMPLEMENTED (sanitize_text_field, sanitize_textarea_field, sanitize_email, sanitize_key)
- SQL injection protection: SAFE (WordPress APIs only)
- XSS protection: IMPLEMENTED (esc_html, esc_attr throughout)
- CSRF protection: IMPLEMENTED (nonce + wp_verify_nonce)
- Captcha integration: IMPLEMENTED (3 providers, configurable)
## Recommendations
## Tech Debt (Non-Critical)
### Before Completing Milestone
1. **Decide on i18n:** Accept German-only for v1.0 or implement before shipping
2. **Fix session bug:** Replace `session_id()` with reliable alternative
3. **Decide on additional work sections:** Ship without or implement
| Phase | Item | Priority |
|-------|------|----------|
| 06 | No admin resend email feature | Low (documented future feature) |
| 06 | No email queue/retry mechanism | Low |
| 07 | reCAPTCHA v3 no non-JS fallback | Low |
| 07 | Simple email regex validation | Low |
### For Next Milestone
- i18n with full English translation (if deferred)
- Additional work sections integration
- Sonstiges free text field
- Admin resend email
- Production testing across hosting environments
**Total: 4 items across 2 phases — all low priority, none blocking**
## Summary
All 9 requirements satisfied. All 9 phases complete. All 5 E2E flows verified end-to-end. Cross-phase integration score 10/10 with zero orphaned exports and zero broken connections. All critical gaps from the previous audit (2026-02-06) have been closed by Phases 8 and 9. Only low-priority tech debt remains (future features, minor edge cases).
The plugin is ready for production deployment.
---
*Generated by gsd-integration-checker on 2026-02-06*
*Generated on 2026-02-07 by milestone audit orchestrator*
*Integration check: gsd-integration-checker*
*Previous audit: 2026-02-06 (gaps_found → all closed)*