Commit Graph

20 Commits

Author SHA1 Message Date
Paul Huliganga e995ac2764 Return auth callbacks to current page 2026-04-22 22:09:15 -04:00
Paul Huliganga e19bd68ebd Use Adobe OAuth callback flow in web UI 2026-04-22 12:00:17 -04:00
Paul Huliganga 8f0b14bc62 Scope audit activity by session 2026-04-22 11:29:37 -04:00
Paul Huliganga fb54426bea Add tester activity audit log 2026-04-22 11:10:57 -04:00
Paul Huliganga aaa72be54e Show connected account names in UI 2026-04-22 10:52:55 -04:00
Paul Huliganga 90113a6514 Add DocuSign account picker 2026-04-21 23:06:48 -04:00
Paul Huliganga eb9ce84001 Add multi-user web auth sessions 2026-04-21 21:05:15 -04:00
Paul Huliganga 3b27a0fd5b Update DocuSign auth docs and coverage 2026-04-21 16:26:13 -04:00
Paul Huliganga b2bbcac842 feat(issues): structured field-issue reporting throughout migration pipeline
Replaces flat warning strings with machine-readable FieldIssue objects
(code, field_name, message, severity) emitted during compose and surfaced
in all migration result paths via a new field_issues[] key.

Codes: CROSS_RECIPIENT_CONDITIONAL, UNSUPPORTED_OPERATOR, HIDE_ACTION,
MULTI_PREDICATE, INVALID_PARENT_TAB, FIELD_TYPE_SKIPPED, PARTIAL_FIELD_TYPE

Cross-recipient conditional detection: compose now builds a field→assignee
map and flags conditions where the trigger field belongs to a different
recipient — the main cause of the CONDITIONALTAB_HAS_INVALID_PARENT 400.

UI changes:
- Success rows with field_issues show ⚠️ icon + amber "partial" badge
- Results, History & Audit, and Template Detail history tab all show
  field issues grouped by code in collapsible sections within expanded rows

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:25:23 -04:00
Paul Huliganga 53eb206d89 fix(compose): strip invalid conditionalParentLabel refs before upload
DocuSign returns CONDITIONALTAB_HAS_INVALID_PARENT when a conditional tab
references a parent that doesn't exist or is a forbidden type (signature,
initial, auto-filled). Added _strip_invalid_conditionals() post-processing
pass that validates all conditionalParentLabel values against the actual
built tabs and removes any that won't pass DocuSign validation, logging a
warning for each. Also updated verify tests for the template role-fetch step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:09:11 -04:00
Paul Huliganga 0dcf7193e0 feat(ui-phase-22): smoke test checklist, README update, execution board
118/118 backend tests passing (108 original + 7 verify + 3 templates).
UI-SMOKE-TEST.md: 11-section manual checklist covering project switcher,
auth, templates, dry run, real migration, issues view, verification,
history, and settings.
README: new Web UI section with navigation table, 7-step workflow guide,
and project/customer context explanation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:43:44 -04:00
Paul Huliganga 11b646d3b7 feat(ui-phase-19): verification — send/status/void API + frontend polling
Backend (web/routers/verify.py): POST /send (creates envelope from template),
GET /status/{id} (polls envelope state), POST /void/{id} (voids test envelope).
Registered in app.py. 7 tests passing.

Frontend (verification.js): table of migrated templates, Send Test button opens
dialog with pre-filled name/email from settings, polling every 5s, per-row
status updates (Sent → Delivered → Verified), Void button for cleanup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:40:19 -04:00
Paul Huliganga 023c3928f3 feat(ui-phase-16): templates view — readiness badges, filter bar, detail tabs
Backend: add blockers[] and warnings[] to GET /api/templates/status. Calls
validate_template() on downloaded templates; returns empty lists if not
downloaded. 3 new tests (10 total, all passing).

Frontend (templates.js): filterable/sortable table with readiness badges
(Blocked/Caveats/Ready/Migrated/Needs Update), bulk-select toolbar,
per-row migrate/detail buttons, and template detail view with 3 tabs
(Overview, Issues, Migration History).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:26:49 -04:00
Paul Huliganga 342e8c3471 feat(phases-8-13): blueprint alignment — normalized schema, validation, migration options, retry, security, batch
Phase 8: Normalized intermediate schema (src/models/normalized_template.py, src/services/mapping_service.py)
  - Platform-agnostic NormalizedTemplate as pipeline bridge
  - PDF SHA-256 checksums computed during normalization
  - 13 tests passing

Phase 9: Validation service + report builder (src/services/validation_service.py, src/reports/report_builder.py)
  - Blockers (no recipients, no documents) halt migration
  - Warnings (no fields, unassigned roles, unsupported features) logged
  - Structured MigrationReport with per-template status
  - 20 tests passing

Phase 10: Migration options API (web/routers/migrate.py)
  - source_template_ids, dry_run, overwrite_if_exists, include_documents options
  - Backward compatible with legacy adobe_template_ids field
  - 7 tests passing

Phase 11: Retry with exponential backoff (src/utils/retry.py)
  - retry_with_backoff and async_retry_with_backoff decorators
  - 429/5xx detection via check_response_retryable
  - 14 tests passing

Phase 12: Security hardening (src/utils/log_sanitizer.py)
  - SanitizingFilter redacts tokens, JWTs, base64 PDF content from logs
  - 15 tests passing

Phase 13: Batch migration API
  - POST /api/migrate/batch — async background job with job_id
  - GET /api/migrate/batch/{job_id} — poll progress and results
  - 6 tests passing

Full suite: 108/108 tests passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 02:19:38 -04:00
Paul Huliganga c63d49e208 fix: Adobe Sign connects via .env refresh token; restore DocuSign OAuth
- GET /api/auth/adobe/connect: reads ADOBE_REFRESH_TOKEN from .env,
  refreshes the access token, stores in session — no login required
- Falls back to OAuth dialog only if no .env credentials exist
- Restores DocuSign OAuth start/callback endpoints alongside JWT connect
- 33/33 tests passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 15:27:42 -04:00
Paul Huliganga aa88ba363d fix: DocuSign connects via JWT grant from .env, no browser sign-in
Replaces the DocuSign OAuth redirect flow with a direct JWT grant call
using credentials already in .env (same as the CLI). Clicking
"Connect DocuSign" now calls GET /api/auth/docusign/connect which calls
get_access_token() and stores the result in the session cookie.

No email sign-in required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 15:24:50 -04:00
Paul Huliganga 1383586d91 fix: use existing Adobe Sign redirect URI (localhost:8080) in web UI
The Adobe Sign OAuth app has https://localhost:8080/callback registered
(same as CLI). The web UI now uses the same manual paste flow:
- GET /api/auth/adobe/url returns the auth URL for the frontend to open
- POST /api/auth/adobe/exchange accepts the full redirect URL the user
  copies after authorizing, extracts the code, exchanges for tokens
- Dialog UI guides user through the 3-step process

DocuSign keeps its standard redirect callback flow unchanged.
31/31 tests passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 15:20:10 -04:00
Paul Huliganga 51f532f452 feat: idempotent upload + FastAPI web UI with full test coverage
Phase 1 — Idempotent upload:
- upload_docusign_template.py now upserts: PUT if template with same name
  exists (most recently modified), POST otherwise
- --force-create flag to bypass upsert

Phase 2-6 — FastAPI web UI:
- web/app.py: FastAPI app with /health, static file serving
- web/routers/auth.py: Adobe Sign + DocuSign OAuth start/callback/disconnect
- web/routers/templates.py: template listing + migration status badges
  (not_migrated / migrated / needs_update)
- web/routers/migrate.py: POST /api/migrate pipeline + GET /api/migrate/history
- web/static/: vanilla HTML/CSS/JS side-by-side template browser UI

Phase 7 — Tests (29/29 passing):
- test_upload_upsert.py: 4 upsert unit tests
- test_api_health/auth/templates/migrate.py: full API coverage
- test_e2e.py: 7-step full pipeline end-to-end test
- test_regression.py: compose output vs snapshots for 3 real templates
- conftest.py: --update-snapshots CLI option

Docs: IMPLEMENTATION-PLAN.md, updated EXECUTION-BOARD.md + architecture.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 14:47:27 -04:00
Paul Huliganga 7aac78f3a4 docs: document Adobe Sign non-standard refresh token endpoint
Adobe Sign uses /oauth/v2/refresh (not /oauth/v2/token) for token
refresh — a deviation from the OAuth2 spec that caused all refresh
attempts to fail with a misleading "Invalid grant_type" error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 12:35:17 -04:00
Paul Huliganga e30e9d4f14 docs: README, platform quirks, validation notes, and sample reference data
README.md — rewritten to reflect actual usage: setup, auth flows, CLI
commands for all three scripts, and links to field-mapping and quirks docs.

tests/PLATFORM-QUIRKS.md — documents confirmed bugs and API quirks found
during development: numberTabs rendering as text+validation (DocuSign API
bug), multi-location field fix, zero-width tab fix, Company/Title contentType
SIGNER_ prefix variant from Adobe Sign API.

tests/ — SCENARIOS, EDGE-CASES, FIELD-TYPE-REGRESSION test planning docs.

validation/ — research notes: field eval, mapping ambiguity log, decision
log, conditional logic analysis, round-trip eval, DocuSign ingest eval.

docs/architecture.md — system architecture overview.
api-samples.md — annotated Adobe Sign API response examples.
PRODUCT-SPEC.md — product requirements and migration scope definition.
sample-templates/ — JSON fixtures (NDA, onboarding, sales contract) for
offline testing; PDFs excluded from version control.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 19:45:46 -04:00