167 lines
7.3 KiB
Markdown
167 lines
7.3 KiB
Markdown
# Execution Board (Living Kanban)
|
||
|
||
*Last updated: 2026-04-21*
|
||
|
||
---
|
||
|
||
## Completed (v1 — CLI Pipeline)
|
||
|
||
- [x] Adobe Sign OAuth setup + token auto-refresh (`src/auth_adobe.py`, `src/adobe_api.py`) ✅
|
||
- [x] Template download pipeline — metadata, fields, docs, PDF (`src/download_templates.py`) ✅
|
||
- [x] Field type mapping — all major Adobe field types → DocuSign tabs ✅ (see `field-mapping.md`)
|
||
- [x] Coordinate system fix — y passthrough (top-origin, no conversion needed) ✅
|
||
- [x] Conditional logic mapping → `conditionalParentLabel/Value` ✅ (see `validation/conditional-logic-eval.md`)
|
||
- [x] DocuSign template JSON composition (`src/compose_docusign_template.py`) ✅
|
||
- [x] DocuSign JWT upload (`src/upload_docusign_template.py`) ✅
|
||
- [x] Regression checklist for all field types ✅ (see `tests/FIELD-TYPE-REGRESSION.md`)
|
||
- [x] End-to-end round-trip test (3 real Adobe templates → DocuSign) ✅
|
||
|
||
---
|
||
|
||
## Phase 1 — Idempotent Upload ✅ (2026-04-17)
|
||
|
||
- [x] Add `find_existing_template(name)` to `upload_docusign_template.py` — lists DS templates by name, returns most-recently-modified match
|
||
- [x] Change `upload_template()` to upsert: PUT if match found, POST if not
|
||
- [x] Add `--force-create` CLI flag to bypass upsert
|
||
- [x] Write `tests/test_upload_upsert.py` — 4 tests passing
|
||
|
||
---
|
||
|
||
## Phase 2 — FastAPI Backend Foundation ✅ (2026-04-17)
|
||
|
||
- [x] Add new dependencies to `requirements.txt`
|
||
- [x] Create `web/` directory structure (app.py, config.py, session.py, routers/, static/)
|
||
- [x] Implement `GET /health` endpoint
|
||
- [x] Write `tests/test_api_health.py` — 2 tests passing
|
||
|
||
---
|
||
|
||
## Phase 3 — Auth Endpoints ✅ (2026-04-17)
|
||
|
||
- [x] Implement Adobe Sign OAuth start + callback + disconnect in `web/routers/auth.py`
|
||
- [x] Implement DocuSign OAuth start + callback + disconnect
|
||
- [x] Implement `GET /api/auth/status`
|
||
- [x] Write `tests/test_api_auth.py` — 4 tests passing
|
||
|
||
---
|
||
|
||
## Phase 4 — Template Listing API ✅ (2026-04-17)
|
||
|
||
- [x] Implement `GET /api/templates/adobe` in `web/routers/templates.py`
|
||
- [x] Implement `GET /api/templates/docusign`
|
||
- [x] Implement `GET /api/templates/status` — computes `not_migrated / migrated / needs_update`
|
||
- [x] Write `tests/test_api_templates.py` — 7 tests passing
|
||
|
||
---
|
||
|
||
## Phase 5 — Migration API ✅ (2026-04-17)
|
||
|
||
- [x] Implement `POST /api/migrate` in `web/routers/migrate.py` — download → compose → upsert pipeline
|
||
- [x] Implement `GET /api/migrate/history` — reads/writes `migration-output/.history.json`
|
||
- [x] Write `tests/test_api_migrate.py` — 7 tests passing
|
||
|
||
---
|
||
|
||
## Phase 6 — Frontend ✅ (2026-04-17)
|
||
|
||
- [x] Create `web/static/index.html` — side-by-side template browser layout
|
||
- [x] Create `web/static/app.js` — auth status check, template listing, migrate flow, history
|
||
- [x] Create `web/static/style.css` — status badges, layout
|
||
|
||
---
|
||
|
||
## Phase 7 — End-to-End & Regression ✅ (2026-04-17)
|
||
|
||
- [x] Write `tests/test_e2e.py` — 7-step full pipeline test, 1 test passing
|
||
- [x] Write `tests/test_regression.py` — compose pipeline vs snapshots, 4 tests passing
|
||
- [x] Create `tests/fixtures/expected/` — snapshot JSONs for David Tag Demo, NDA, Rob Test
|
||
- [x] Full suite: **29/29 passing**
|
||
|
||
---
|
||
|
||
## Phase 8 — Normalized Intermediate Schema ✅ (2026-04-21)
|
||
|
||
- [x] Create `src/models/` package with `__init__.py`
|
||
- [x] Implement `src/models/normalized_template.py` — pydantic model with NormalizedTemplate, NormalizedField, NormalizedRole, NormalizedDocument
|
||
- [x] Implement `src/services/` package with `__init__.py`
|
||
- [x] Implement `src/services/mapping_service.py` — Adobe Sign folder → NormalizedTemplate converter with checksums
|
||
- [x] Write `tests/test_normalized_schema.py` — 13 tests passing (model construction, serialization, real fixture round-trips)
|
||
- [x] Update README
|
||
|
||
---
|
||
|
||
## Phase 9 — Validation Service ✅ (2026-04-21)
|
||
|
||
- [x] Implement `src/services/validation_service.py` — `ValidationResult(blockers, warnings)`, checks for no recipients, no documents, no fields, missing roles, unsupported features
|
||
- [x] Implement `src/reports/report_builder.py` — `MigrationReport`, `TemplateReport`, `MigrationStatus` enum, factory functions
|
||
- [x] Integrate validation into migration pipeline (`_run_validation` in `web/routers/migrate.py`) — blocks on blockers
|
||
- [x] Implement `compare_field_counts(normalized, ds_template)` post-migration check
|
||
- [x] Write `tests/test_validation_service.py` — 20 tests passing
|
||
- [x] Update README
|
||
|
||
---
|
||
|
||
## Phase 10 — Migration Options API ✅ (2026-04-21)
|
||
|
||
- [x] Extend `POST /api/migrate` request body: `source_template_ids[]`, `target_folder`, `options.dry_run`, `options.overwrite_if_exists`, `options.include_documents`
|
||
- [x] Implement dry-run path — validate + compose without creating DocuSign templates (`status=dry_run`)
|
||
- [x] Implement `overwrite_if_exists=false` — skip already-migrated templates (`status=skipped`)
|
||
- [x] Implement `include_documents` toggle — strips `documentBase64` from payload when false
|
||
- [x] Keep backward compatibility with legacy `adobe_template_ids` field
|
||
- [x] Write `tests/test_migration_options.py` — 7 tests passing
|
||
- [x] Update README
|
||
|
||
---
|
||
|
||
## Phase 11 — Rate Limiting & Retry with Backoff ✅ (2026-04-21)
|
||
|
||
- [x] Implement `src/utils/retry.py` — `retry_with_backoff` (sync) and `async_retry_with_backoff` decorators with exponential backoff + max_delay cap
|
||
- [x] Implement `check_response_retryable(status_code)` — returns True for 429/500/502/503/504
|
||
- [x] Write `tests/test_retry.py` — 14 tests passing (exponential delay, max delay, exception filtering, async)
|
||
- [x] Update README
|
||
|
||
---
|
||
|
||
## Phase 12 — Security Hardening & Audit Trail ✅ (2026-04-21)
|
||
|
||
- [x] Implement `src/utils/log_sanitizer.py` — `redact()`, `redact_dict()`, `SanitizingFilter`, `install_sanitizing_filter()`
|
||
- [x] Redacts: Bearer tokens, JWT-style tokens, key=value secret assignments, long base64 payloads (PDF content)
|
||
- [x] PDF checksum (SHA-256) computed in `mapping_service.adobe_folder_to_normalized()` and stored in `NormalizedDocument.checksum_sha256`
|
||
- [x] Write `tests/test_security.py` — 15 tests passing
|
||
- [x] Update README
|
||
|
||
---
|
||
|
||
## Phase 13 — Batch Migration API ✅ (2026-04-21)
|
||
|
||
- [x] Implement `POST /api/migrate/batch` — async background job, returns `job_id` immediately
|
||
- [x] Implement `GET /api/migrate/batch/{job_id}` — poll job status, progress, results, summary
|
||
- [x] Implement retry for failed templates (one retry on upload failures)
|
||
- [x] In-memory job store with progress tracking (`_batch_jobs` dict)
|
||
- [x] Write `tests/test_batch_migration.py` — 6 tests passing
|
||
- [x] Update README
|
||
|
||
---
|
||
|
||
## Full Test Suite ✅ (2026-04-21)
|
||
|
||
**108/108 tests passing**
|
||
|
||
---
|
||
|
||
## Gitea
|
||
|
||
- [x] Committed and pushed all changes (2026-04-17)
|
||
- [ ] Commit and push Phase 8–13 work (ui-redesign branch)
|
||
|
||
---
|
||
|
||
## Results & Lessons Learned
|
||
|
||
- (2026-04-14) NDA, David Tag Demo, Rob Test all converted cleanly
|
||
- (2026-04-15) Coordinate bug fixed — y is top-origin in both platforms, no conversion needed
|
||
- (2026-04-15) Paul Adobe Template created via API; Company/Title fields require manual UI fix (API limitation)
|
||
- (2026-04-17) v2 planning complete — idempotent upload + web UI implementation begins
|
||
- (2026-04-21) Blueprint comparison complete — added normalized schema, validation service, migration options, rate-limit/retry, security hardening, and batch migration phases (Phases 8–13)
|
||
- (2026-04-21) Phases 8–13 fully implemented — 108/108 tests passing on ui-redesign branch
|