docs: update README, field-mapping, and EXECUTION-BOARD for Phase 23 and post-redesign fixes

Reflects all implementation from this session: 7 post-redesign bug fixes
(routing, polling, branding, verification role names, conditional parent 400s,
failure UX, template detail history expand), and Phase 23 structured field
issue reporting end-to-end. Test count updated to 119/119.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Paul Huliganga 2026-04-21 15:34:06 -04:00
parent b2bbcac842
commit 15c50f05e3
3 changed files with 122 additions and 28 deletions

View File

@ -133,7 +133,7 @@ Then open [http://localhost:8000](http://localhost:8000) in your browser.
### Workflow
1. **Create a project** — the switcher modal opens on first run; name it after the customer.
2. **Connect platforms** — click the Adobe Sign and DocuSign chips in the top bar.
2. **Connect platforms** — click the Adobe Sign and Docusign chips in the top bar.
3. **Review templates** — the Templates view shows readiness badges:
- **Ready** (green) — no issues, safe to migrate
- **Caveats** (amber) — warnings exist; migration will proceed but check Issues view
@ -141,9 +141,10 @@ Then open [http://localhost:8000](http://localhost:8000) in your browser.
- **Migrated** (cobalt) — successfully migrated and up to date
- **Needs Update** (amber) — Adobe template modified after last migration
4. **Resolve issues** — check Issues & Warnings before migrating blocked templates.
5. **Migrate** — select templates, click Migrate Selected, configure options (dry run, overwrite, target folder), monitor progress.
6. **Verify** — on the Verification screen, send test envelopes and confirm receipt.
7. **Audit** — History & Audit logs every migration with checksums and export.
5. **Migrate** — select templates, click Migrate Selected, configure options (dry run, overwrite, target folder), monitor progress. Failed rows show the error inline; a summary hint appears if any templates fail.
6. **Review field issues** — successfully migrated templates may show an amber **partial** badge if features were dropped during migration (e.g. cross-recipient conditionals, unsupported operators). Expand any result row to see grouped field-issue details.
7. **Verify** — on the Verification screen, send test envelopes to confirm templates work end-to-end. Polling checks every 30 seconds and times out after 5 minutes; production deployments should use Docusign Connect (webhooks) instead.
8. **Audit** — History & Audit logs every migration with checksums and export. Rows with field issues show the same grouped breakdown on expand.
### Project / customer context
@ -157,7 +158,7 @@ Create one project per customer to keep history and settings separate.
## Running tests
```bash
pytest tests/ -v # full suite (118 tests)
pytest tests/ -v # full suite (119 tests)
pytest tests/test_regression.py -v # compose regression only
pytest tests/test_regression.py --update-snapshots # regenerate snapshots after intentional changes
```
@ -228,6 +229,22 @@ Each template is validated before migration:
Unsupported features flagged for manual review: conditional HIDE actions, JavaScript validators, calculated fields, webhook associations, niche authentication methods.
## Field issues (partial migration)
Beyond blockers and warnings, the compose step emits structured **field issues** when a field migrates successfully but something was silently dropped or approximated. Each issue has a machine-readable code:
| Code | Meaning |
|---|---|
| `CROSS_RECIPIENT_CONDITIONAL` | Show/hide condition references a field on a different recipient — DocuSign does not support cross-recipient conditional logic |
| `UNSUPPORTED_OPERATOR` | Condition uses NOT_EQUALS / GT / LT etc. — only EQUALS is supported |
| `HIDE_ACTION` | Adobe HIDE condition has no DocuSign equivalent — field will always be visible |
| `MULTI_PREDICATE` | AND/OR multi-condition logic reduced to first EQUALS predicate only |
| `INVALID_PARENT_TAB` | Conditional parent references a non-existent tab or a forbidden tab type (signature/auto-fill tabs cannot be parents) |
| `FIELD_TYPE_SKIPPED` | INLINE_IMAGE or PARTICIPATION_STAMP — no DocuSign equivalent, field dropped |
| `PARTIAL_FIELD_TYPE` | FILE_CHOOSER → signerAttachmentTabs, or STAMP → stampTabs — field migrated but behaviour differs |
Templates with field issues are marked with a **partial** badge in the UI. Field issues are stored in `field_issues[]` on every migration result record and displayed grouped by code in all result views.
---
## Security
@ -244,6 +261,7 @@ Unsupported features flagged for manual review: conditional HIDE actions, JavaSc
src/
models/
normalized_template.py # Platform-agnostic intermediate schema
field_issue.py # Structured field-issue model + issue codes
services/
mapping_service.py # Adobe Sign → NormalizedTemplate converter
validation_service.py # Pre/post migration checks (blockers + warnings)
@ -265,13 +283,34 @@ web/
config.py # Environment-based settings
session.py # Signed cookie session helpers
routers/
auth.py # Adobe Sign + DocuSign OAuth endpoints
auth.py # Adobe Sign + Docusign OAuth endpoints
templates.py # Template listing + migration status API
migrate.py # Migration trigger, batch, + history API
verify.py # Verification envelope send / status / void
static/
index.html # Web UI (side-by-side browser + migrate flow)
app.js # Vanilla JS frontend
style.css # Styles + status badge colours
index.html # SPA shell (left nav, router outlet, top bar)
css/
tokens.css # Docusign 2024 brand custom properties
base.css # Reset, typography, utility classes
nav.css # Left sidebar navigation
cards.css # Cards, badges, result rows, field-issue groups
modals.css # Modal dialogs, migration progress
tables.css # Sortable/filterable tables
forms.css # Form inputs, toggles
js/
app.js # Entry point — router, auth, nav badges
router.js # Hash-based SPA router (#/templates default)
state.js # Global state with pub/sub
api.js # Fetch wrappers for all backend endpoints
auth.js # Auth chips, OAuth flow, toast notifications
templates.js # Templates view + detail (overview/issues/history tabs)
migration.js # Migration modal, progress polling, results view
issues.js # Issues & Warnings view
verification.js # Verification view (send/poll/void envelopes)
history.js # History & Audit view
settings.js # Settings view
project.js # Project/customer context (localStorage)
utils.js # escHtml, formatDate, renderFieldIssues, etc.
tests/
test_normalized_schema.py # Normalized model + mapping service tests
@ -283,8 +322,9 @@ tests/
test_upload_upsert.py # Upsert logic unit tests
test_api_health.py # Health endpoint
test_api_auth.py # OAuth endpoint tests
test_api_templates.py # Template listing + status tests
test_api_templates.py # Template listing + status tests (10 tests)
test_api_migrate.py # Migration API tests
test_api_verify.py # Verification envelope API tests (9 tests)
test_e2e.py # Full pipeline end-to-end test
test_regression.py # Compose output vs snapshots
fixtures/expected/ # Regression snapshots (3 real templates)

View File

@ -1,6 +1,6 @@
# Execution Board (Living Kanban)
*Last updated: 2026-04-21*
*Last updated: 2026-04-21 (post-redesign bug fixes + Phase 23)*
---
@ -208,8 +208,40 @@
- [x] Full backend test suite: **118/118 tests passing**
- [x] Update `README.md` — new UI navigation guide, workflow, project context
- [x] Update EXECUTION-BOARD.md — all phases complete
- [ ] Push `ui-redesign` branch to Gitea
- [ ] Open PR to `master`
- [x] Push `ui-redesign` branch to Gitea
- [x] Open PR to `master`
---
## Post-Redesign Bug Fixes ✅ (2026-04-21)
Bugs discovered during live testing after Phase 22.
- [x] **Docusign branding** — replaced all "DocuSign" with "Docusign" (2024 brand) across 8 frontend files
- [x] **Template detail routing**`router.js` `parseHash` used wrong slice indices (`slice(0,3)` instead of `slice(0,2)`), causing `#/templates/:id` to always fall through to the list view
- [x] **Migration polling infinite loop**`pollJob` only checked `'done'`/`'complete'` but backend emits `'completed'`; migration progress spinner never resolved
- [x] **Verification envelope role names** — hardcoded `roleName: "Signer"` meant envelopes sent without tags; now fetches actual template role names from Docusign API before sending, falls back to `"Signer"` only on fetch failure
- [x] **Verification polling rate** — changed from 5 s to 30 s per Docusign rate-limit guidance; added 5-minute timeout with amber "Timed Out" badge; note: production should use Docusign Connect webhooks
- [x] **CONDITIONALTAB_HAS_INVALID_PARENT (400)** — compose was emitting `conditionalParentLabel` pointing to signature/auto-fill tabs (forbidden as parents) or to fields on different recipients (cross-recipient). Fixed by post-processing strip pass in `_strip_invalid_conditionals`
- [x] **Migration modal failure UX** — failed/blocked rows now show the error message in small red text beneath the template name; completion summary shows count + "select View Results for details" hint
- [x] **Template detail history tab** — migration history rows with errors/blockers/warnings now expand inline (matching History & Audit behaviour)
---
## Phase 23 — Structured Field Issue Reporting ✅ (2026-04-21)
- [x] `src/models/field_issue.py``FieldIssue` dataclass with `code`, `field_name`, `message`, `severity`; 7 named codes: `CROSS_RECIPIENT_CONDITIONAL`, `UNSUPPORTED_OPERATOR`, `HIDE_ACTION`, `MULTI_PREDICATE`, `INVALID_PARENT_TAB`, `FIELD_TYPE_SKIPPED`, `PARTIAL_FIELD_TYPE`
- [x] `src/compose_docusign_template.py` — all warning paths now also emit structured `FieldIssue`; cross-recipient detection added (builds `{field_name → assignee}` map, checks predicate fieldName assignee before applying conditional); return signature changed to `(template, warnings, issues)`
- [x] `web/routers/migrate.py` — captures `field_issues` from compose result; all `_migrate_one` return paths include `field_issues: []`
- [x] `web/static/js/utils.js``renderFieldIssues()` groups issues by code in collapsible sections; `bindFieldIssueToggles()` wires expand/collapse
- [x] `web/static/js/migration.js` — results view: ⚠️ icon + amber **partial** badge for success-with-issues; field issue groups in expanded rows
- [x] `web/static/js/history.js` — amber **partial** badge + field issue groups in expanded rows
- [x] `web/static/js/templates.js` — template detail history tab shows field issues with partial badge per record
- [x] `web/static/css/cards.css``.field-issues-block`, `.field-issue-group`, `.field-issue-row` styles
- [x] `tests/test_regression.py` — updated for 3-tuple compose return
- [x] `tests/test_api_verify.py` — updated for template role-fetch + added fallback test (9 tests)
- [x] Full test suite: **119/119 tests passing**
- [x] Updated `README.md`, `field-mapping.md`, `EXECUTION-BOARD.md`
---
@ -219,8 +251,7 @@
- [x] Committed Phase 813 work (ui-redesign branch, 2026-04-21)
- [x] Committed UI mockup + Docusign 2024 brand (ui-redesign branch, 2026-04-21)
- [x] Committed Phases 1422 UI implementation (ui-redesign branch, 2026-04-21)
- [ ] Push ui-redesign branch to Gitea
- [ ] Open PR to master
- [x] Pushed ui-redesign branch to Gitea; PR #1 open against master
---
@ -235,3 +266,5 @@
- (2026-04-21) Enterprise UI mockup designed — 8 screens, Docusign 2024 branding, official SVG logo embedded
- (2026-04-21) UI Redesign plan written (Phases 1422) — frontend-only except Phase 16 (readiness data) and Phase 19 (verify API)
- (2026-04-21) Phases 1422 fully implemented — 118/118 tests passing, enterprise UI complete
- (2026-04-21) Post-redesign live testing found 7 bugs — all fixed (routing, polling, branding, verification role names, conditional parent 400s)
- (2026-04-21) Phase 23 complete — structured field issue reporting end-to-end; 119/119 tests passing; cross-recipient conditional now explicitly detected and described rather than silently producing a 400

View File

@ -84,24 +84,39 @@ Tab types that do not merge (only first location used or handled specially):
Adobe Sign `conditionalAction` → DocuSign `conditionalParentLabel` + `conditionalParentValue` on the dependent tab.
| Adobe Sign | DocuSign | Notes |
|-----------------------------------|---------------------------------|-------|
| `predicates[].fieldName` | `conditionalParentLabel` | For radio groups, matches the group name |
| `predicates[].value` | `conditionalParentValue` | The value the trigger must equal to reveal the tab |
| `action: SHOW` | Supported | Tab is hidden until condition is met |
| `action: HIDE` | **Not supported** | No DocuSign equivalent — condition skipped, field always shown |
| `operator: EQUALS` | Supported | Only operator DocuSign supports |
| Other operators | **Not supported** | Condition skipped, warning logged |
| Multiple predicates (ANY/ALL) | **Partial** — first EQUALS only | Warning logged; remaining predicates ignored |
| Adobe Sign | DocuSign | Outcome | Notes |
|-----------------------------------|---------------------------------|---------|-------|
| `predicates[].fieldName` | `conditionalParentLabel` | Mapped | For radio groups, matches the group name |
| `predicates[].value` | `conditionalParentValue` | Mapped | The value the trigger must equal to reveal the tab |
| `action: SHOW` | Supported | Mapped | Tab is hidden until condition is met |
| `action: HIDE` | **Not supported** | Dropped | No DocuSign equivalent — field always shown. `HIDE_ACTION` issue emitted. |
| `operator: EQUALS` | Supported | Mapped | Only operator DocuSign supports |
| Other operators (NOT_EQUALS, etc.)| **Not supported** | Dropped | Condition skipped. `UNSUPPORTED_OPERATOR` issue emitted. |
| Multiple predicates (ANY/ALL) | **Partial** — first EQUALS only | Partial | `MULTI_PREDICATE` issue emitted; remaining predicates ignored |
| Trigger field on a different recipient | **Not supported** | Dropped | DocuSign `conditionalParentLabel` only works within the same recipient's tab set. `CROSS_RECIPIENT_CONDITIONAL` issue emitted. |
| Parent is signature/auto-fill tab | **Not supported** | Stripped | DocuSign forbids signature, initial, dateSign, fullName, email, title tabs as conditional parents. `INVALID_PARENT_TAB` issue emitted. |
## Known Gaps
- **Conditional HIDE**: Adobe Sign can conditionally hide a field. DocuSign only supports
revealing hidden fields — there is no native way to hide a visible field conditionally.
Templates with HIDE conditions will have those fields always visible after migration.
Emits a `HIDE_ACTION` field issue.
- **Cross-recipient conditionals**: Adobe Sign allows field B to appear/hide based on
the value of field A even when A and B belong to different recipients. DocuSign's
`conditionalParentLabel` only works within a single recipient's tab set.
Emits a `CROSS_RECIPIENT_CONDITIONAL` field issue; the condition is dropped.
- **Invalid or forbidden conditional parents**: If the trigger field maps to a signature,
initial, dateSign, fullName, email, or title tab — DocuSign forbids these as conditional
parents and returns `CONDITIONALTAB_HAS_INVALID_PARENT` (400). The compose pipeline
strips these conditions in a post-processing pass and emits an `INVALID_PARENT_TAB`
field issue.
- **Multi-predicate conditions**: Adobe Sign supports ANY/ALL of multiple predicates.
DocuSign only supports a single parent condition per tab. Only the first EQUALS
predicate is mapped; complex conditions require manual rework.
Emits a `MULTI_PREDICATE` field issue.
- **Unsupported operators**: NOT_EQUALS, GT, LT etc. have no DocuSign equivalent.
The condition is dropped. Emits an `UNSUPPORTED_OPERATOR` field issue.
- **DocuSign formula fields**: No Adobe Sign equivalent — flag for manual rewrite.
- **Advanced field validation**: Adobe regex/custom script validation is not mapped;
best-effort via standard DocuSign validation types only.
@ -109,8 +124,14 @@ Adobe Sign `conditionalAction` → DocuSign `conditionalParentLabel` + `conditio
DocuSign `radioGroupTabs` entry with per-location radio button coordinates.
- **Stamp tab account feature**: `stampTabs` requires the stamp/hanko feature to be
enabled on the DocuSign account. Verify before migrating templates that contain
Adobe Sign STAMP fields.
Adobe Sign STAMP fields. Emits a `PARTIAL_FIELD_TYPE` field issue.
- **FILE_CHOOSER → signerAttachmentTabs**: Docusign attachment tabs behave differently
from Adobe file upload fields (different UX, no file type restrictions).
Emits a `PARTIAL_FIELD_TYPE` field issue recommending manual review.
## To Do
- Add conditional logic/rule mapping table
- Document field mask and default value transforms
## Field Issue Codes
All dropped or approximated features are surfaced as structured `FieldIssue` objects
alongside human-readable warning strings. See `src/models/field_issue.py` for the full
list. The UI groups these by code in collapsed sections within migration result rows,
history rows, and the template detail Issues tab.