diff --git a/CHANGELOG.md b/CHANGELOG.md index 258945d..a42f949 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,44 +1,59 @@ # Changelog / 更新记录 -## V0.1.0 Release Candidate +## V0.1.0 — 2026-09-19 English: -* Added V0.1 specification and modular local first architecture. -* Added schema builder domain and JSON Schema generation. -* Added deterministic validation for required, type, regex, numeric range, strict ISO calendar dates, boolean rules, and unexpected output fields. -* Added BYOK adapters for OpenAI, Anthropic, and Gemini, including OpenAI `store: false` and Gemini `responseJsonSchema`. -* Added PDF.js text extraction and Tesseract.js local OCR fallback. -* Added human correction state, provenance fields, and local eval metrics. -* Added IndexedDB project storage and portable project backup and restore. -* Added JSON, CSV, and XLSX export. -* Added React review workspace and Cloudflare Pages deployment configuration. -* Added dependency free domain, Vitest, persistence, component, TypeScript, production build, and Playwright smoke verification. +* Added the V0.1 specification and modular Local First architecture. +* Added browser-side PDF.js text extraction and Tesseract.js OCR fallback for scans and images. +* Added schema building for string, number, date, and boolean fields, plus Required, regex, minimum, maximum, strict ISO date, malformed output, and unknown-field validation. +* Added provider-independent extraction orchestration with BYOK adapters for OpenAI, Anthropic, Gemini, and Qwen. +* Added explicit Qwen region routing for China (Beijing), Singapore, and Hong Kong (China), with no automatic cross-region fallback. +* Added provider verification metadata. Qwen is V0.1 Live Verified; OpenAI, Anthropic, and Gemini remain Experimental until their own real API smoke tests pass. +* Rechecked the V0.1 default model IDs against official provider documentation on 2026-09-19: `gpt-5.6-luna`, `claude-sonnet-5`, `gemini-3.8-flash`, and `qwen3.8-max`. +* Added deterministic local validation immediately after AI prediction and after human correction. +* Added Human-in-the-Loop Review that preserves AI Prediction, Final Value, correction state, validation result, provider, model, region, and processing timestamp. +* Added JSON, CSV, and XLSX export from Final Value. +* Added IndexedDB autosave and startup restoration of the most recently updated project. +* Fixed startup hydration so a new blank project cannot autosave before IndexedDB restoration completes. +* Added versioned portable JSON backup and restore. API keys and original binary documents remain excluded. +* Added local eval metrics derived from validation and human correction state. +* Added React review workspace, Vitest, dependency-free domain tests, TypeScript typecheck, production build verification, and Playwright Chromium smoke tests. +* Deployed the public V0.1 build through Cloudflare Workers + Static Assets at `https://flowextract.edwardxie421.workers.dev`. +* Completed a real production Qwen China (Beijing) smoke test with a fictional invoice: extraction, structured output, validation, human correction, revalidation, JSON/CSV/XLSX export, IndexedDB reload, and Backup/Restore all passed. The API key was not persisted or included in the backup. 中文: * 建立 V0.1 SPEC 和模块化 Local First 架构。 -* 建立 Schema 域模型和 JSON Schema 生成。 -* 建立 Required、类型、正则、数字范围、严格 ISO 日期、布尔值和未知输出字段确定性验证。 -* 建立 OpenAI、Anthropic、Gemini BYOK 适配器,包括 OpenAI `store: false` 和 Gemini `responseJsonSchema`。 -* 建立 PDF.js 文本提取和 Tesseract.js 本地 OCR fallback。 -* 建立人工修订状态、provenance 字段和本地 Evals。 -* 建立 IndexedDB 项目存储与便携备份恢复。 -* 建立 JSON、CSV、XLSX 导出。 -* 建立 React Review 工作区和 Cloudflare Pages 部署配置。 -* 建立无依赖核心域、Vitest、持久化、组件、TypeScript、生产构建和 Playwright smoke 验证。 +* 建立浏览器端 PDF.js 文本提取,以及扫描件和图片的 Tesseract.js OCR fallback。 +* 建立 String、Number、Date、Boolean Schema,以及 Required、Regex、Minimum、Maximum、严格 ISO 日期、Malformed Output、Unknown Fields 验证。 +* 建立与 Provider 无关的 Extraction 编排,并接入 OpenAI、Anthropic、Gemini、Qwen BYOK Adapter。 +* 建立 Qwen 中国大陆(北京)、新加坡、中国香港显式地域路由,禁止自动跨地域 fallback。 +* 建立 Provider Verification Metadata。Qwen 在 V0.1 中为 Live Verified;OpenAI、Anthropic、Gemini 在各自真实 API Smoke Test 完成前保持 Experimental。 +* 2026-09-19 根据官方文档重新核对 V0.1 默认模型 ID:`gpt-5.6-luna`、`claude-sonnet-5`、`gemini-3.8-flash`、`qwen3.8-max`。 +* AI Prediction 生成后立即执行本地确定性 Validation,人工修订后基于 Final Value 重新 Validation。 +* 建立 Human-in-the-Loop Review,保留 AI Prediction、Final Value、Correction、Validation、Provider、Model、Region 和处理时间。 +* JSON、CSV、XLSX 均使用 Final Value 导出。 +* 建立 IndexedDB 自动保存,并在启动时恢复最近更新项目。 +* 修复启动 Hydration 竞态,避免 IndexedDB 恢复完成前保存空白新项目。 +* 建立版本化 Project Backup / Restore;API Key 和原始二进制文档均不进入备份。 +* 建立基于 Validation 和 Human Correction 的本地 Evals。 +* 建立 React Review 工作区、无依赖 Domain Tests、Vitest、TypeScript Typecheck、Production Build 和 Playwright Chromium Smoke。 +* 公共 V0.1 使用 Cloudflare Workers + Static Assets 部署:`https://flowextract.edwardxie421.workers.dev`。 +* 已使用虚构 Invoice 在生产环境完成 Qwen 中国大陆(北京)真实 Smoke Test:Extraction、Structured Output、Validation、Human Correction、Revalidation、JSON/CSV/XLSX、IndexedDB Reload、Backup/Restore 全部通过;API Key 未持久化,也未进入 Backup。 ### Verification / 验证 -GitHub Actions now performs the full V0.1 release gate on Node.js 22: +The final release gate requires and has automated coverage for: -1. Dependency free domain tests. +1. Dependency-free domain tests. 2. Reproducible dependency install with `npm ci`. 3. Vitest suite. 4. TypeScript project typecheck. 5. Vite production build. 6. Playwright Chromium smoke test. +7. Cloudflare Workers production build. -The full gate passed on the public `main` branch during release preparation on September 18, 2026. +The production BYOK smoke test is manual by design because FlowExtract does not persist provider credentials in the repository, CI, IndexedDB, or backup files. -GitHub Actions 现在使用 Node.js 22 执行完整 V0.1 发布门禁,包括核心域测试、`npm ci`、Vitest、TypeScript 类型检查、Vite 生产构建和 Playwright Chromium smoke。2026 年 9 月 18 日公开仓库 `main` 分支已通过完整流程。 +最终发布门禁包含无依赖 Domain Tests、`npm ci`、Vitest、TypeScript Typecheck、Vite Production Build、Playwright Chromium Smoke 和 Cloudflare Workers Production Build。真实 BYOK Smoke Test 保持人工执行,因为 FlowExtract 不在仓库、CI、IndexedDB 或 Backup 中保存 Provider 凭据。 diff --git a/README.md b/README.md index 5c7815a..a3c2961 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ FlowExtract is an open source browser application for turning PDFs and document The review step is the product focus. AI makes the first prediction. Deterministic rules identify missing, malformed, or out of range values. The user sees the source alongside the predicted and final values and corrects only what needs attention. -## Current V0.1 development scope +## V0.1 scope Supported input targets: @@ -23,7 +23,7 @@ Supported input targets: Schema fields support `string`, `number`, `date`, and `boolean`, plus required fields, regex patterns, and numeric minimum and maximum rules. -BYOK provider adapters are included for OpenAI, Anthropic, Gemini, and Qwen (Alibaba Cloud Model Studio). Model names are editable because provider model lifecycles change independently from FlowExtract. Provider availability is tracked separately from adapter implementation: until a real API smoke test passes, a provider remains marked Experimental even when its contract tests pass. +BYOK provider adapters are included for OpenAI, Anthropic, Gemini, and Qwen (Alibaba Cloud Model Studio). Model names are editable because provider model lifecycles change independently from FlowExtract. Qwen is live-verified for V0.1 against Alibaba Cloud Model Studio in China (Beijing). OpenAI, Anthropic, and Gemini remain Experimental: their adapters and contract tests are included, but a real API smoke test has not been completed for this release. Exports include JSON, CSV, and XLSX. Project state is stored in IndexedDB. Portable JSON backup and restore are included. @@ -79,29 +79,31 @@ npm run test:e2e `npm run test:domain` runs dependency free Node 22 domain tests. It remains usable when package installation is unavailable. -## Cloudflare Pages deployment +## Cloudflare Workers deployment -FlowExtract requires no runtime server. - -Use these Pages settings: +FlowExtract requires no application backend. The public V0.1 deployment uses Cloudflare Workers + Static Assets with Git integration. ```text +Production branch: main Build command: npm run build -Build output directory: dist +Deploy command: npx wrangler deploy +Static assets: ./dist Node version: 22 ``` -A free `pages.dev` subdomain is enough for the first public MVP. Do not add a paid domain, database, server, or FlowExtract funded AI account before product validation requires it. +Production: `https://flowextract.edwardxie421.workers.dev` + +The repository `wrangler.jsonc` configures `./dist` as SPA static assets. V0.1 stays on the free `workers.dev` hostname and does not add a paid domain, database, server-side AI proxy, or FlowExtract-funded AI account. ## Provider notes -Default model strings are convenience values only and are editable in the UI. +Default model strings are convenience values only and are editable in the UI. The V0.1 defaults were rechecked against official provider documentation on 2026-09-19: `gpt-5.6-luna`, `claude-sonnet-5`, `gemini-3.8-flash`, and `qwen3.8-max`. OpenAI uses the Responses API with structured JSON output and requests `store: false`. Anthropic uses the Messages API and structured output. The browser adapter includes Anthropic's direct browser access header. Gemini uses `generateContent` with `responseJsonSchema`. Qwen uses Alibaba Cloud Model Studio's OpenAI-compatible Chat Completions interface with strict JSON Schema output. Qwen region selection is explicit; FlowExtract does not automatically retry a document in another region. Browser BYOK is a deliberate V0.1 tradeoff for a zero backend, user controlled tool. The key is never embedded in the application and is cleared on reload, but it is still accessible to the page runtime while entered. OpenAI and Google both recommend keeping long lived production API keys on a server. For V0.1 testing, use a dedicated provider key with the smallest practical permissions, quota, and spend limits. A future hardened option can use a user run local companion or provider specific short lived authorization when available. -Provider APIs can change. Verify current provider documentation before a release. +Provider APIs can change. Recheck current provider documentation before each release. A valid model ID does not imply that FlowExtract has completed a live API smoke test for that provider. ## Known V0.1 limitations @@ -118,6 +120,8 @@ Provider APIs can change. Verify current provider documentation before a release * `CONTRIBUTING.md` * `SECURITY.md` * `CHANGELOG.md` +* `docs/deployment-cloudflare-workers.md` +* `docs/release-v0.1.md` ## License diff --git a/README.zh-CN.md b/README.zh-CN.md index 7dc900a..4b837b6 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -23,7 +23,7 @@ Review 是产品重点。AI 先给出预测,确定性 Validation Rules 检查 Schema 支持 `string`、`number`、`date`、`boolean`,并支持 Required、正则格式、数字最小值和最大值。 -BYOK Provider 已建立 OpenAI、Anthropic、Gemini、Qwen(阿里云百炼 / Model Studio)适配器。模型名称可以直接编辑,避免 Provider 更新模型后必须重新发布 FlowExtract。Provider 的“代码已适配”和“真实 API 已验证”分开记录:即使 Contract Tests 已通过,在真实 API Smoke Test 成功前仍标记为 Experimental。 +BYOK Provider 已建立 OpenAI、Anthropic、Gemini、Qwen(阿里云百炼 / Model Studio)适配器。模型名称可以直接编辑,避免 Provider 更新模型后必须重新发布 FlowExtract。Qwen 已在 V0.1 中使用阿里云百炼中国大陆(北京)地域完成真实 API 端到端验证。OpenAI、Anthropic、Gemini 仍标记为 Experimental:适配器和 Contract Tests 已具备,但本次 Release 尚未完成真实 API Smoke Test。 导出支持 JSON、CSV、XLSX。项目数据保存在 IndexedDB,同时提供可移植 JSON 项目备份和恢复。 @@ -79,29 +79,31 @@ npm run test:e2e `npm run test:domain` 使用 Node 22 执行无依赖核心域测试,在 npm 依赖暂时无法安装时仍可运行。 -## Cloudflare Pages 免费部署 +## Cloudflare Workers 免费部署 -FlowExtract 不需要运行时服务器。 - -Pages 配置: +FlowExtract 不需要应用后端。V0.1 公共环境实际使用 Cloudflare Workers + Static Assets,并通过 Git 集成自动部署。 ```text +Production branch: main Build command: npm run build -Build output directory: dist +Deploy command: npx wrangler deploy +Static assets: ./dist Node version: 22 ``` -第一阶段使用免费的 `pages.dev` 子域即可。在产品得到真实验证以前,不购买域名、数据库、服务器,也不使用 FlowExtract 自己承担费用的 AI 账户。 +生产地址:`https://flowextract.edwardxie421.workers.dev` + +仓库中的 `wrangler.jsonc` 把 `./dist` 配置为 SPA 静态资源。V0.1 继续使用免费的 `workers.dev` 地址,不增加付费域名、数据库、服务端 AI 代理或 FlowExtract 自己承担费用的 AI 账户。 ## Provider 说明 -UI 中的默认模型名称只是便利默认值,用户可以修改。 +UI 中的默认模型名称只是便利默认值,用户可以修改。V0.1 默认模型 ID 已于 2026-09-19 根据各 Provider 官方文档重新核对:`gpt-5.6-luna`、`claude-sonnet-5`、`gemini-3.8-flash`、`qwen3.8-max`。 OpenAI 使用 Responses API 的结构化 JSON 输出,并显式发送 `store: false`。Anthropic 使用 Messages API 和 structured output,并在浏览器适配器中加入其浏览器直连 Header。Gemini 使用 `generateContent` 和 `responseJsonSchema`。Qwen 使用阿里云 Model Studio 的 OpenAI-compatible Chat Completions 和严格 JSON Schema 输出。Qwen Region 必须由用户明确选择;某个地域失败时,FlowExtract 不会把文档自动重试到其他地域。 浏览器 BYOK 是 V0.1 在零后端约束下采用的明确取舍。API Key 不会嵌入应用,也会在刷新页面后清除,但输入期间页面运行时仍可以访问该 Key。OpenAI 和 Google 的官方安全说明都建议生产环境的长期 API Key 放在服务端。V0.1 测试应使用独立 Provider Key,并尽量限制权限、额度和消费上限。后续可增加由用户自己运行的本地 companion,或在 Provider 支持时采用短期授权。 -Provider API 会变化,正式 Release 前需要再次核对官方文档。 +Provider API 会变化,每次 Release 前都需要重新核对官方文档。模型 ID 有效并不等于 FlowExtract 已完成该 Provider 的真实 API Smoke Test。 ## V0.1 已知限制 @@ -114,3 +116,9 @@ Provider API 会变化,正式 Release 前需要再次核对官方文档。 ## 许可证 MIT + + +## 部署与发布文档 + +* `docs/deployment-cloudflare-workers.md` +* `docs/release-v0.1.md` diff --git a/SECURITY.md b/SECURITY.md index 3654d73..7114f93 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,9 +8,9 @@ Do not open a public issue containing API keys, private documents, credentials, ## V0.1 trust boundary / V0.1 信任边界 -FlowExtract has no application backend. Documents are parsed locally. Parsed text is sent directly to the user's selected AI provider only when the user starts extraction. API keys remain in volatile browser state and must never enter IndexedDB, backups, logs, fixtures, screenshots, or repository files. +FlowExtract has no application backend. Documents are parsed locally. Parsed text is sent directly to the user's selected AI provider only when the user starts extraction. For Qwen, the user explicitly selects the provider region and FlowExtract never automatically retries the same document in another region after failure. API keys remain in volatile browser state and must never enter IndexedDB, backups, logs, fixtures, screenshots, or repository files. -FlowExtract 没有应用后端。文档在本地解析。只有用户主动执行提取时,解析后的文本才会直接发送给用户选择的 AI Provider。API Key 只能存在于浏览器临时状态,禁止进入 IndexedDB、备份、日志、测试 fixtures、截图和仓库文件。 +FlowExtract 没有应用后端。文档在本地解析。只有用户主动执行提取时,解析后的文本才会直接发送给用户选择的 AI Provider。Qwen 地域由用户明确选择,FlowExtract 不会在请求失败后自动把同一文档重试到其他地域。API Key 只能存在于浏览器临时状态,禁止进入 IndexedDB、备份、日志、测试 fixtures、截图和仓库文件。 ## Logging / 日志 diff --git a/docs/deployment-cloudflare-pages.md b/docs/deployment-cloudflare-pages.md deleted file mode 100644 index ead9f30..0000000 --- a/docs/deployment-cloudflare-pages.md +++ /dev/null @@ -1,62 +0,0 @@ -# Cloudflare Pages deployment - -FlowExtract V0.1 is designed to run as a static browser application with no FlowExtract backend. - -## Cost boundary - -Use the Cloudflare Free plan and the generated `pages.dev` hostname. Do not add a paid domain, database, server, Pages Functions, Workers, storage product, analytics SaaS, or FlowExtract funded AI account for V0.1. - -Cloudflare documents a Free plan for Pages. As of September 2026, the Free plan allows 500 builds per month with one build at a time. Static asset requests are free and unlimited. Verify current Cloudflare limits before changing the deployment model. - -## Git integration - -Connect Cloudflare Pages to the public GitHub repository: - -`edwardsage419/FlowExtract` - -Use these settings: - -```text -Production branch: main -Root directory: / -Build command: npm run build -Build output directory: dist -``` - -The repository includes `.node-version` with Node.js 22 so the Pages build runtime is pinned independently of the platform default. - -Do not configure API keys as Cloudflare environment variables. FlowExtract BYOK keys are entered by the user at runtime and are intentionally absent from the deployment environment. - -## First deployment verification - -After Cloudflare reports a successful deployment, verify the generated `pages.dev` site in a clean browser profile. - -1. The FlowExtract heading and Document, Schema, AI Extraction, and Review sections render. -2. A public fixture PDF or image can be selected. -3. A schema field can be added and edited. -4. Refreshing the page clears any API key entered in the current session. -5. Project state can be saved locally and restored from IndexedDB. -6. JSON and CSV export work without provider access. -7. XLSX export downloads a valid workbook. -8. Browser developer tools show no request to a FlowExtract application backend. - -For a provider smoke test, use a dedicated low quota test key and a non-sensitive fixture. Never paste a production credential into an issue, commit, log, screenshot, or chat. - -## Security headers - -`public/_headers` is deployed with the static assets. Review it whenever external provider endpoints, OCR assets, or third party libraries change. - -## Rollback - -If a release deployment is faulty, stop further product changes, identify the last known good Git commit, and redeploy that revision from Cloudflare Pages. Keep deployment history tied to Git commits so rollback remains reproducible. - -## References - -Cloudflare Pages limits: -https://developers.cloudflare.com/pages/platform/limits/ - -Cloudflare Pages Git integration: -https://developers.cloudflare.com/pages/get-started/git-integration/ - -Cloudflare Pages build image: -https://developers.cloudflare.com/pages/configuration/build-image/ diff --git a/docs/deployment-cloudflare-workers.md b/docs/deployment-cloudflare-workers.md new file mode 100644 index 0000000..a2756e5 --- /dev/null +++ b/docs/deployment-cloudflare-workers.md @@ -0,0 +1,91 @@ +# Cloudflare Workers + Static Assets deployment + +FlowExtract V0.1 is deployed as a static browser application on Cloudflare Workers using Static Assets. It has no FlowExtract application backend, database, server-side AI proxy, or server-side credential store. + +## Production deployment + +Repository: + +`edwardsage419/FlowExtract` + +Production URL: + +`https://flowextract.edwardxie421.workers.dev` + +Cloudflare Workers Builds is connected to GitHub. Production deploys are created from `main`. + +Build settings: + +```text +Production branch: main +Root directory: / +Build command: npm run build +Deploy command: npx wrangler deploy +Node version: 22 +``` + +Preview builds may use `npx wrangler versions upload`. Production promotion must come from the verified `main` branch. + +The repository contains `wrangler.jsonc`: + +```json +{ + "$schema": "node_modules/wrangler/config-schema.json", + "name": "flowextract", + "compatibility_date": "2026-09-18", + "assets": { + "directory": "./dist", + "not_found_handling": "single-page-application" + } +} +``` + +The Vite production build writes static files to `dist/`. No Worker `main` script is configured. + +## Cost boundary + +V0.1 stays on Cloudflare's Free plan and uses the generated `workers.dev` hostname. Do not add a paid domain, database, object storage, AI proxy, analytics SaaS, or FlowExtract-funded AI account before product validation requires it. + +Cloudflare documents static-asset requests for Workers as free and unlimited. If the architecture later adds a Worker script or other Cloudflare products, re-check current pricing and limits before deployment. + +## Security boundary + +Do not configure user AI API keys as Cloudflare environment variables, repository secrets, or deployment credentials. + +Users enter BYOK credentials in the browser at runtime. Keys remain in volatile page memory and are cleared on reload. Parsed document text is sent directly from the browser to the provider selected by the user; Cloudflare does not proxy AI extraction requests. + +For Qwen, the user-selected region determines the Alibaba Cloud endpoint. FlowExtract does not automatically retry the same document in another region. + +## Production verification + +After a successful production deployment, verify the `workers.dev` site: + +1. FlowExtract renders the Document, Schema, AI Extraction, Review, and Export workflow. +2. A public or synthetic PDF can be parsed locally. +3. Schema fields can be created and edited. +4. API keys are empty after a page reload. +5. Parsed document text, schema, extraction, validation, and human corrections restore from IndexedDB. +6. The original uploaded binary is not restored from IndexedDB. +7. JSON, CSV, and XLSX exports use Final Value. +8. Backup and Restore preserve project data and corrections but exclude credentials and the original binary document. +9. Browser developer tools show no FlowExtract application backend receiving document text or provider credentials. + +The V0.1 production smoke test used a fictional invoice fixture and Qwen in China (Beijing). It verified extraction, validation, correction, revalidation, export, IndexedDB reload, and backup/restore without sharing the API key. + +## Rollback + +If a production deployment is faulty, stop further release work, identify the last known-good Git commit, and redeploy that revision through Workers Builds. Keep deployment history tied to Git commits so rollback remains reproducible. + +## References + +Cloudflare Workers Static Assets: +https://developers.cloudflare.com/workers/static-assets/ + +Cloudflare Workers Builds Git integration: +https://developers.cloudflare.com/workers/ci-cd/builds/git-integration/ + +Workers Builds configuration: +https://developers.cloudflare.com/workers/ci-cd/builds/configuration/ + +Static Assets billing and limitations: +https://developers.cloudflare.com/workers/static-assets/billing-and-limitations/ diff --git a/docs/release-v0.1.md b/docs/release-v0.1.md index 7396c58..c521473 100644 --- a/docs/release-v0.1.md +++ b/docs/release-v0.1.md @@ -4,7 +4,7 @@ This checklist is the final gate for the first public FlowExtract release. ## Automated gate -All checks must be green on `main`: +All checks must be green on the final `main` commit: 1. `npm run test:domain` 2. `npm ci --no-audit --no-fund` @@ -12,17 +12,33 @@ All checks must be green on `main`: 4. `npm run typecheck` 5. `npm run build` 6. `npm run test:e2e` +7. Cloudflare Workers production build + +Do not create the release tag while any gate is failing or pending. ## Provider verification gate Provider adapter implementation and live provider verification are separate release facts. -* OpenAI, Anthropic, and Gemini may ship as **Experimental** when their contract tests pass but a real API call has not been completed. -* Qwen is the V0.1 live verification target. It remains **Experimental** until the production deployment completes a real BYOK smoke test. -* A live Qwen smoke test must use a public or fictional fixture and must verify: HTTP success, structured output parsing, local validation, review correction, revalidation, and JSON/CSV/XLSX export. -* API keys must never be committed to GitHub, stored in CI secrets for this smoke test, copied into project backups, or shared in screenshots. -* Qwen region selection must be explicit. A failed request must never trigger an automatic retry in another region. -* The selected provider region is provenance and must be retained with the extraction record. +* Qwen is **Live Verified** for V0.1 using Alibaba Cloud Model Studio in China (Beijing). +* OpenAI, Anthropic, and Gemini ship as **Experimental**. Their adapters and contract tests are included, but V0.1 has not completed a real API smoke test for those providers. +* The live Qwen smoke test used a fictional invoice and verified: HTTP success, strict structured output parsing, local validation, human correction, revalidation, JSON/CSV/XLSX export, IndexedDB reload, and Backup/Restore. +* The AI prediction `1333.8` remained preserved after the reviewed Final Value was corrected to `1333.81`. +* Export used Final Value consistently across JSON, CSV, and XLSX. +* Reload restored parsed text, schema, extraction, prediction, correction, and validation from IndexedDB while the API key remained empty. +* Backup/Restore preserved project data and Qwen provenance (`provider`, `model`, `providerRegion`) while excluding the API key and original binary document. +* Qwen region selection is explicit. A failed request must never trigger an automatic retry in another region. + +## Provider model IDs + +The editable V0.1 default model IDs were rechecked against official provider documentation on 2026-09-19: + +* OpenAI: `gpt-5.6-luna` +* Anthropic: `claude-sonnet-5` +* Gemini: `gemini-3.8-flash` +* Qwen: `qwen3.8-max` + +Model validity does not imply live FlowExtract verification. Recheck official provider documentation for every release. ## Repository gate @@ -36,30 +52,37 @@ Confirm these files are present and current: * `CHANGELOG.md` * `docs/superpowers/specs/2026-09-18-flowextract-v0.1-design.md` * `docs/superpowers/plans/2026-09-18-flowextract-v0.1-phase1.md` -* `docs/deployment-cloudflare-pages.md` +* `docs/deployment-cloudflare-workers.md` +* `docs/release-v0.1.md` * `tests/fixtures/README.md` +* `wrangler.jsonc` Confirm the repository contains no API keys, private documents, or user data. ## Deployment gate -Create the Cloudflare Pages project with Git integration and deploy `main` using the settings in `docs/deployment-cloudflare-pages.md`. +Production uses Cloudflare Workers + Static Assets with Git integration. + +Production URL: + +`https://flowextract.edwardxie421.workers.dev` -Use the free `pages.dev` hostname. Do not purchase a domain for V0.1. +Required deployment settings are documented in `docs/deployment-cloudflare-workers.md`. -Perform the clean browser verification from the deployment guide. +The production deployment must come from the verified `main` commit. Do not configure user AI API keys as Cloudflare environment variables. ## Release gate -After deployment verification: +After the final `main` CI and production deployment are green: -1. Create Git tag `v0.1.0` from the verified `main` commit. +1. Create Git tag `v0.1.0` from that exact verified `main` commit. 2. Create a GitHub Release titled `FlowExtract V0.1.0`. -3. Use the V0.1 section of `CHANGELOG.md` as the release notes basis. -4. Include the live `pages.dev` URL in the release. -5. State the Local First and BYOK security boundaries clearly. -6. Attach no private documents, API keys, or test credentials. +3. Use the V0.1.0 section of `CHANGELOG.md` as the release notes basis. +4. Include `https://flowextract.edwardxie421.workers.dev` in the release. +5. State the Local First, browser BYOK, provider verification, and Qwen region boundaries clearly. +6. State that OpenAI, Anthropic, and Gemini are Experimental in V0.1. +7. Attach no private documents, API keys, test credentials, or user data. -## Post release observation +## Post-release observation -Track real user feedback without expanding V0.1 scope immediately. Record recurring requests around document types, fields, OCR failures, review time, repeat usage, and willingness to pay as candidates for V0.2. +Track real user feedback without expanding V0.1 scope immediately. Record recurring requests around document types, fields, OCR failures, extraction errors, review time, correction rate, repeat usage, provider availability, and willingness to pay as candidates for V0.2. diff --git a/docs/superpowers/plans/2026-09-18-flowextract-v0.1-phase1.md b/docs/superpowers/plans/2026-09-18-flowextract-v0.1-phase1.md index 1f78c15..0c3f4a1 100644 --- a/docs/superpowers/plans/2026-09-18-flowextract-v0.1-phase1.md +++ b/docs/superpowers/plans/2026-09-18-flowextract-v0.1-phase1.md @@ -1,5 +1,7 @@ # FlowExtract V0.1 Phase 1 Implementation Plan +> Historical implementation plan. Final V0.1 deployment and provider verification status are recorded in the current design spec, `docs/release-v0.1.md`, and `docs/deployment-cloudflare-workers.md`. + > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Deliver a browser-only end-to-end MVP path from document ingestion through schema definition, BYOK AI extraction, deterministic validation, human review, local persistence, and JSON/CSV/XLSX export. @@ -76,7 +78,7 @@ **Files:** * Create `src/features/providers/types.ts`. -* Create provider helpers and adapters for OpenAI, Anthropic, and Gemini. +* Create provider helpers and adapters for OpenAI, Anthropic, Gemini, and Qwen. * Test response parsing and normalized errors. **Interfaces:** @@ -157,7 +159,7 @@ **Files:** * Create `README.md`, `README.zh-CN.md`, `LICENSE`, `CONTRIBUTING.md`, `SECURITY.md`, `CHANGELOG.md`. -* Create Cloudflare Pages guidance and GitHub Actions CI. +* Create Cloudflare Workers + Static Assets guidance and GitHub Actions CI. * Add `playwright.config.ts` and browser smoke test. **Interfaces:** diff --git a/docs/superpowers/specs/2026-09-18-flowextract-v0.1-design.md b/docs/superpowers/specs/2026-09-18-flowextract-v0.1-design.md index 24068b7..49df9ea 100644 --- a/docs/superpowers/specs/2026-09-18-flowextract-v0.1-design.md +++ b/docs/superpowers/specs/2026-09-18-flowextract-v0.1-design.md @@ -20,7 +20,7 @@ V0.1 excludes accounts, subscriptions, Stripe, cloud databases, cloud file stora ## 3. Fixed constraints 1. Fixed operating cost must remain USD 0 per month before real users and revenue. -2. The application must be deployable as static assets to Cloudflare Pages. +2. The application must be deployable as static assets to Cloudflare Workers + Static Assets on the Free plan. 3. User documents must not be uploaded to a FlowExtract controlled server. 4. AI calls use BYOK and go directly from the browser to the provider selected by the user. 5. API keys remain in volatile UI state only. They are not persisted, logged, exported, or committed. @@ -36,7 +36,7 @@ Core modules: * `features/documents`: file acceptance, PDF text extraction, image OCR, document metadata. * `features/schema`: schema definitions, schema builder state, conversion to JSON Schema. -* `features/providers`: provider interface plus OpenAI, Anthropic, and Gemini adapters. +* `features/providers`: provider interface plus OpenAI, Anthropic, Gemini, and Qwen adapters, including explicit Qwen region routing. * `features/extraction`: provider independent extraction orchestration and response normalization. * `features/validation`: deterministic validation of AI output against field definitions and rules. * `features/review`: editable field review model and issue focused UI. @@ -99,6 +99,7 @@ The UI composes these modules in one workspace. Business logic stays out of Reac * schemaId * provider * model +* providerRegion optional * processedAt * rawResponse optional * fields @@ -160,9 +161,11 @@ interface AIProvider { } ``` -`ProviderExtractionInput` includes API key, model, document text, and JSON Schema. Provider adapters own endpoint URLs, headers, request bodies, and provider response parsing. +`ProviderExtractionInput` includes API key, model, document text, JSON Schema, and optional provider region metadata. Provider adapters own endpoint URLs, headers, request bodies, provider response parsing, and provider-specific region resolution. -V0.1 includes browser adapters for OpenAI, Anthropic, and Gemini. Model identifiers are editable in the UI so provider model lifecycle changes do not require a FlowExtract release. +V0.1 includes browser adapters for OpenAI, Anthropic, Gemini, and Qwen. Model identifiers are editable in the UI so provider model lifecycle changes do not require a FlowExtract release. Qwen region selection is explicit and must never automatically fall back across regions after a failed request. + +Provider implementation status is separate from live verification status. Qwen is Live Verified for V0.1 through a production China (Beijing) smoke test. OpenAI, Anthropic, and Gemini remain Experimental until their own live API smoke tests pass. Provider errors are normalized into safe messages. API keys and full document text are never logged. @@ -172,7 +175,7 @@ The normalized provider result is a JSON object whose keys correspond to schema Providers are prompted to return only the requested fields. The response passes through JSON parsing and structural validation before becoming an ExtractionRecord. -V0.1 provenance stores provider, model, timestamp, document id, prediction, final value, validation issues, correction state, and optional source evidence returned by the provider. Exact bounding box provenance is deferred. +V0.1 provenance stores provider, model, optional provider region, timestamp, document id, prediction, final value, validation issues, correction state, and optional source evidence returned by the provider. Exact bounding box provenance is deferred. ## 10. Validation @@ -210,13 +213,13 @@ Exports use final reviewed values. * JSON: object plus optional provenance envelope. * CSV: one row, headers from schema keys, RFC style escaping. -* XLSX: one worksheet using SheetJS. +* XLSX: one worksheet using ExcelJS. The export module is independent from UI code and covered by tests. ## 13. Local persistence and backup -IndexedDB stores project records under a versioned database. Autosave occurs after meaningful project changes with debounce in the UI. +IndexedDB stores project records under a versioned database. Autosave occurs after meaningful project changes with debounce in the UI. On startup, FlowExtract restores the most recently updated local project after IndexedDB hydration completes; autosave must not run before that initial hydration finishes. Backup exports a portable JSON file containing version, project metadata, parsed document text, schema, extraction, and validation state. Restore validates the backup format before writing it locally. @@ -260,9 +263,9 @@ Priority automated tests: ## 17. Deployment -`npm run build` generates static assets in `dist/`. Cloudflare Pages can deploy with build command `npm run build` and output directory `dist`. +`npm run build` generates static assets in `dist/`. V0.1 production uses Cloudflare Workers + Static Assets with `wrangler.jsonc` pointing to `./dist` and SPA fallback enabled. Cloudflare Workers Builds connects to GitHub and deploys verified `main` commits to the free `workers.dev` hostname. -No runtime server, database, paid domain, or paid SaaS is required. +No FlowExtract runtime backend, database, paid domain, or paid SaaS is required. ## 18. V0.1 release gate diff --git a/src/App.test.tsx b/src/App.test.tsx index a28ccc5..3bd2911 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -22,6 +22,8 @@ describe('FlowExtract workspace', () => { expect(screen.getByText(/2\. Schema/i)).toBeInTheDocument(); expect(screen.getByText(/3\. AI Extraction/i)).toBeInTheDocument(); expect(screen.getByText(/4\. Review/i)).toBeInTheDocument(); + expect(screen.getByText('v0.1.0')).toBeInTheDocument(); + expect(screen.getByRole('option', { name: /Qwen \(Alibaba Cloud\) — Verified in Beijing/i })).toBeInTheDocument(); }); diff --git a/src/App.tsx b/src/App.tsx index fe410fb..71325d0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -138,7 +138,7 @@ export default function App() { return (
-
FX

FlowExtract

v0.1 dev

Local first AI assisted document extraction, validation and human review.

+
FX

FlowExtract

v0.1.0

Local first AI assisted document extraction, validation and human review.

props.onProviderChange(e.target.value as ProviderId)}> {Object.entries(PROVIDER_METADATA).map(([id, item]) => ( - + ))} @@ -41,7 +41,7 @@ export function ExtractionPanel(props: ExtractionPanelProps) {

Document text will be sent only to the selected Qwen region ({region?.dataLocation}). FlowExtract never automatically falls back to another region.

)} -

Provider status: {metadata.verification === 'verified' ? 'live verified' : 'experimental / contract-tested until a live smoke test passes'}.

+

Provider status: {verification === 'verified' ? 'live verified for the selected region' : 'experimental / contract-tested until a live smoke test passes for the selected region'}.

The key is kept only in this page session. It is never saved to IndexedDB or project backups.

Browser BYOK exposes the entered key to this page runtime. For testing, use a dedicated provider key with a low quota or spend limit.

diff --git a/src/features/providers/providers.node.test.ts b/src/features/providers/providers.node.test.ts index b687748..c007315 100644 --- a/src/features/providers/providers.node.test.ts +++ b/src/features/providers/providers.node.test.ts @@ -1,6 +1,7 @@ import assert from 'node:assert/strict'; import test from 'node:test'; import { createProvider, parseProviderJson } from './providers.ts'; +import { getProviderVerification } from './types.ts'; const jsonSchema = { type: 'object', properties: { amount: { type: ['number', 'null'] } }, required: ['amount'], additionalProperties: false }; @@ -117,3 +118,10 @@ test('default provider fetch keeps the browser fetch receiver valid', async () = globalThis.fetch = originalFetch; } }); + +test('Qwen live verification is scoped to Beijing', () => { + assert.equal(getProviderVerification('qwen', 'cn-beijing'), 'verified'); + assert.equal(getProviderVerification('qwen', 'ap-southeast-1'), 'experimental'); + assert.equal(getProviderVerification('qwen', 'cn-hongkong'), 'experimental'); + assert.equal(getProviderVerification('openai'), 'experimental'); +}); diff --git a/src/features/providers/types.ts b/src/features/providers/types.ts index a1f5871..cf263c2 100644 --- a/src/features/providers/types.ts +++ b/src/features/providers/types.ts @@ -5,15 +5,22 @@ export type ProviderVerification = 'verified' | 'experimental'; export interface ProviderMetadata { label: string; verification: ProviderVerification; + verifiedRegions?: QwenRegion[]; } export const PROVIDER_METADATA: Record = { openai: { label: 'OpenAI', verification: 'experimental' }, anthropic: { label: 'Anthropic', verification: 'experimental' }, gemini: { label: 'Gemini', verification: 'experimental' }, - qwen: { label: 'Qwen (Alibaba Cloud)', verification: 'experimental' }, + qwen: { label: 'Qwen (Alibaba Cloud)', verification: 'experimental', verifiedRegions: ['cn-beijing'] }, }; +export function getProviderVerification(id: ProviderId, region?: QwenRegion): ProviderVerification { + const metadata = PROVIDER_METADATA[id]; + if (id === 'qwen' && region && metadata.verifiedRegions?.includes(region)) return 'verified'; + return metadata.verification; +} + export const QWEN_REGIONS: Record = { 'cn-beijing': { label: 'China (Beijing)',