Two fixes from first real-Word testing of the unmocked versioning flow:
- fields value length: remove the limit entirely (was 10,000, briefly
100,000) — real court documents run 100-200 pages with content
controls several hundred thousand chars long; callers are Bearer-only
and the column is Postgres jsonb (up to ~255MB), so no storage
bottleneck. Structural guards stay: ≤1,000 keys (was 100), key ≤200
chars, value must be string.
- getVersions in versioningService now maps the history 404 to an empty
list: files stamped SavedByAddIn back in the mock era enter the
tracking phase before any real upload exists, so the pane shows
"ยังไม่มี version ในระบบ" and Save & Version creates v1 (implicit
document creation) instead of surfacing a 404 error banner. Other
errors still propagate.
Tests: 288/288 (new cases — 1M-char value passes, key cap 1,000/1,001,
history 404 -> []). E2E against MinIO: 50k and 1M-char Thai field values
upload 200 and roundtrip byte-exact through jsonb. Docs synced:
PLAN-DOCVER §1, CLAUDE.md.
Co-Authored-By: Claude Code <noreply@anthropic.com>
Replace the in-memory versioningService with real calls to the docver
group (/api/documents/*) via apiClient with the ticket-issued Bearer;
keep the mock only for ?addindemo (authService.isDemoMode).
- uploadVersion: multipart POST /api/documents/versions (file, optional
pdf when non-empty, clientVersionId, fields JSON, trimmed message,
fileName) — identity fields are never sent (userId/userName/templateId
in the form = 400 per the 2026-10-22 contract; docId comes from the
fid claim)
- getVersions: GET → DocumentVersionDTO mapped to VersionRecord (adds
optional createdByUserName; history panel shows it with userId
fallback)
- getDownloadLink: GET presigned URL (+ ?format=pdf)
- apiClient.toUrl: empty NEXT_PUBLIC_ADDIN_API_BASE_URL = same-origin
through withBasePath (/docedit/api/...); the env is now only for a
split deployment (must include basePath, HTTPS)
- documentId/templateId params stay in signatures but are not sent
- tests: versioningService.test.ts covers both modes (real sign-in via
signInWithTicket, FormData contract assertions, DTO mapping, format
query, 401 -> AuthRequiredError, demo mock without network)
- docs sync: WORDADDIN-DEV (new "การรันกับ backend จริง" section),
addin-ui-flow status note, PLAN-DOCVER §8, PLAN-ADDIN-AUTH §12, CLAUDE.md
Verified: tsc clean, 286/286 tests, full E2E against MinIO (ticket ->
token -> upload docx / docx+pdf -> history -> presigned download of both
formats).
Co-Authored-By: Claude Code <noreply@anthropic.com>
Rename tests/wordaddin/ticket-auth-crash-repro.test.ts to
ticket-auth-flow.test.ts and strip the temporary [DBG-r3p1] markers.
The debug session closed with an environment cause (stale Next server
holding the port / corrupted .next chunks), not a code defect, so the
suite stays as regression coverage for the signInWithTicket service
layer: single token fetch per fid, token reuse on reopen without
re-hitting /token, memory-fallback session teardown, and no uncaught
throw/rejection on every failure path (missing/invalid ticket, expired
ticket, server 401, webview without crypto.subtle).
Co-Authored-By: Claude Code <noreply@anthropic.com>
Replace the token/owner pass-through with the ticket flow from
docs/requirement/addin-workflow.md (full plan: docs/PLAN-ADDIN-AUTH.md):
- utils/docver-ticket.ts: shared pure ticket parse + hex digest helpers,
client/server inject their own crypto (Web Crypto / node:crypto)
- lib/addin-ticket.ts + POST /api/documents/token second entry: body
{ticket_data, HmacSha256} verified server-side (HMAC timing-safe + exp,
secret ADDIN_TICKET_SECRET -> SECRET -> "super_secret"); x-api-key path
unchanged
- wordaddin: ticketService (Web Crypto HMAC, localStorage session
wordaddin-auth keyed by fid, same-origin token request), authService
rewrite (7-step flow, silent renew), apiClient 401 renew-retry once,
metadataService reads ticket_data/HmacSha256, no-access messages per
cause
- scripts/make-ticket-docx.mjs: dev tool to stamp tickets onto any .docx
for testing in real Word
- app/wordaddin/error.tsx: error boundary showing the real error + stack
in the pane (webviews have no devtools)
- tests: docver-ticket + addin-ticket unit suites (21 cases) + temporary
crash repro suite for the ongoing client-crash debug session
- docs sync: PLAN-DOCVER, WORDADDIN-DEV, addin-ui-flow, openapi (two
request bodies for /token), CLAUDE.md, .env.example
Co-Authored-By: Claude Code <noreply@anthropic.com>