diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 52e0367..4e0777a 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -1,22 +1,29 @@ # Security -## Provider credentials +## Credential protection -Invio `v1.0.0.1.11` stores provider credential values through the owner-approved Python `keyring` integration and requires an approved OS-protected backend. There is no plaintext-file fallback. The normal operational SQLite database stores only an opaque credential reference, and application settings remain non-sensitive. +Invio stores provider credential values through Python `keyring` and requires an approved OS-protected backend. There is no plaintext-file fallback. The operational SQLite database stores only opaque credential references; ordinary application settings remain non-sensitive. -If protected credential storage is unavailable, Account persistence fails closed. If a persisted credential entry is missing/unreadable at startup, the Account metadata is retained but the runtime Account is restored as `Not Verified`, so the existing P01 Task gates prevent execution. +If protected credential storage is unavailable, Account persistence fails closed. If a persisted credential is missing or unreadable at startup, Account metadata remains visible but runtime state is downgraded to `Not Verified`, preserving the existing Task execution gates. -Do not include provider secrets, exported logs containing sensitive customer data, or local per-user application databases in issues, pull requests, commits, screenshots, or diagnostic archives. +## Transport and provider trust boundaries -## Reporting security issues +Provider HTTPS certificate and hostname verification remain mandatory. On Windows, the shared provider transport uses the native Windows trust store through `truststore`; certificate-verification failures are not silently bypassed. + +External executable provider adapters are trusted code. Invio validates the supported external-adapter/IVX contract and requires the existing explicit trust boundary before executable adapter use. Installing an external provider must not be treated as sandboxing untrusted Python code. + +## Privacy, logs, exports, and local data -Use the repository's private/security reporting channel where available. Do not publish active provider credentials or customer data in a public issue. +Recipient-level delivery reconciliation, structured privacy redaction, safe exports, and closed-history retention controls are implemented through the existing P10/P12 operational contracts. Do not include provider secrets, unredacted customer data, local application databases, protected credential material, or sensitive exported logs in public issues, pull requests, commits, screenshots, or diagnostic archives. -## Current boundary +## Windows release signing -P02 protects credential persistence. Recipient-level delivery reconciliation, generalized PII/log redaction, and full live/native security certification are later production roadmap phases and are not claimed by this release. +The current Windows distribution follows owner-approved Signing Option C and may be unsigned, so Windows can display `Unknown Publisher`. This is a documented distribution boundary, not a claim of Authenticode verification. Use the release checksum asset when verifying downloaded release files. + +## Reporting security issues -P03 verification error summaries are scrubbed against the Account credential values before durable storage. +Use the repository's private/security reporting channel where available. Do not publish active provider credentials, customer data, authorization codes, refresh tokens, local databases, or other sensitive operational evidence in a public issue. +## Current security boundary -`v1.0.0.1.11` additionally persists a fail-closed `Not Verified` downgrade when protected credentials are missing/unreadable and stages Account Edit with a durable `Not Verified` safety marker before crossing the SQLite/keyring boundary. Migration backups use SQLite backup semantics so committed WAL state is not omitted. +The current release combines OS-protected credential persistence, fail-closed credential recovery, mandatory TLS verification, privacy-redacted operational logging/export controls, and explicit trusted external-provider execution boundaries. These controls reduce repository and runtime exposure but do not make third-party providers, provider credentials, user endpoints, or unsigned binaries inherently trusted. diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d08e9..d96a316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,9 @@ - Records the native Windows full regression result from that clean GitHub checkout: **642/642 PASS**, including Phase-4 Dynamic Tags tests and the current schema-v7 migration contracts. - Records successful wheel/P14 audit, native PySide6/keyring/resource smoke, Nuitka OneDir startup, protected-credential and Windows-native-TLS smokes, WiX MSI build/install/run/uninstall, release-payload audit, and artifact upload. - Removes one tracked trailing-whitespace defect from the historical v1.0.0.1.50 patch manifest. -- Synchronizes the release identity to application/wheel `1.0.0.1.50.1`, PE `1.0.1.5001`, MSI `1.1.5001`, and future tag `v1.0.0.1.50.1` using the existing six-part hotfix mapping. +- Synchronizes the release identity to application/wheel `1.0.0.1.50.1`, PE `1.0.1.5001`, MSI `1.1.5001`, and tag `v1.0.0.1.50.1` using the existing six-part hotfix mapping. - No Phase-1 TLS, Phase-2 provider circuit-breaker, Phase-3 sending-control, Phase-4 Dynamic Tags, provider, storage-schema, Task/WorkerManager, credential, OAuth/IVX, or UI/UX behavior changes are introduced. +- Records that tag/release `v1.0.0.1.50.1` was published on 2026-08-18 with wheel, Windows portable ZIP, Windows MSI and release checksum assets. ## v1.0.0.1.50 — Deterministic Dynamic Tags V1 diff --git a/README.md b/README.md index d15b8ad..35dfa75 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ -## Current release-readiness baseline — v1.0.0.1.50.1 +## Current authoritative state — v1.0.0.1.50.1 -`v1.0.0.1.50.1` is a maintenance-only release-readiness synchronization over the owner-frozen `v1.0.0.1.50` Phase-4 baseline. The exact parent commit `b87b412413f8788656c89b3b97a487d855d10d5f` passed GitHub Actions run `32109507918`: Linux and Windows jobs were green, Windows executed **642/642 tests PASS**, and the complete wheel → Nuitka OneDir → protected credential/TLS smoke → WiX MSI → P14 release-payload → artifact-upload chain passed. Phase 1 through Phase 4 runtime behavior remains frozen; this hotfix only closes release-record/status drift, one tracked Markdown trailing-whitespace defect, and current version/release metadata. +Invio `v1.0.0.1.50.1` is the current published product release. The release was published on 2026-08-18 after the Phase-4 release-readiness chain completed successfully. Application/wheel version remains `1.0.0.1.50.1` and operational SQLite remains schema **v7**. + +Subsequent repository-maintenance Phase-01 (F-001/F-002) and Phase-02 (F-003/F-004) corrected source-audit, CI source-only, checksum-lifecycle and workspace/source-provenance defects without changing application runtime, providers, UI/UX, schema, version, build artifacts, or the published release. Historical sections below describe the state of their named versions at that time; they are not alternate current baselines. ## Accepted Phase-4 baseline — v1.0.0.1.50 @@ -8,15 +10,15 @@ Invio v1.0.0.1.50 implements the owner-approved **Deterministic Dynamic Tags V1* Phase 4 advances operational storage additively from schema v6 to **schema v7** so Settings-default dynamic-name provenance and the immutable Task Dynamic Tags version/UTC reference survive restart. Existing v6 Customer/Task rows migrate with Dynamic Tags disabled, preserving pre-Phase-4 literal behavior for already captured executions. No new UI page, preview workflow, provider-specific hidden tags, provider API capability, WorkerManager architecture, TLS behavior, Phase-2 circuit breaker, or Phase-3 scheduling behavior is introduced. GitHub Actions run `32109507918` passed on exact commit `b87b412413f8788656c89b3b97a487d855d10d5f`, including native Windows **642/642 PASS** and the complete Windows distribution chain. -## Current baseline candidate — v1.0.0.1.49.9 +## Historical baseline candidate — v1.0.0.1.49.9 v1.0.0.1.49.9 is a narrow Windows CI correction over the accepted Phase-3 implementation. GitHub Actions run `32097949119` proved the Linux job and all Phase-3 runtime/UI tests green; the Windows job failed only because the new schema-v5→v6 migration test fixture left its own SQLite connections open until temporary-directory cleanup. The fixture now explicitly closes those test connections. Production `DomainStore`, SQLite schema v6, Sending & Retry controls, provider rate ceilings, Phase-1 TLS, Phase-2 fatal-limit semantics, WorkerManager/QThread ownership and all provider/UI workflows remain unchanged. -## Current baseline candidate — v1.0.0.1.49.8 +## Historical baseline candidate — v1.0.0.1.49.8 Phase 3 adds bounded Sending Scheduler / Retry / Delay controls without changing provider business payloads, Phase-1 TLS trust, Phase-2 fatal-limit circuit-breaking, WorkerManager/QThread ownership, or Dynamic Tags. New Tasks freeze their sending controls into the immutable execution snapshot and SQLite schema v6 persists those controls across restart. Defaults preserve v1.49.7 behavior: 30-second Task network timeout, three total automatic attempts, zero additional recipient delay, Stripe 20 requests/second/account, Refrens 1 request/second/account, and no invented Odoo numeric scheduling policy. Provider `Retry-After`, internal retry taxonomy/backoff/jitter/cooldowns and non-idempotent no-blind-replay rules remain authoritative. -## Current baseline candidate — v1.0.0.1.49.7 +## Historical baseline candidate — v1.0.0.1.49.7 v1.49.7 corrects only the verified GitHub Actions P14 release-audit false negative from the v1.49.6 Windows build. Nuitka successfully compiled and executed the native `truststore` TLS backend in both OneDir and MSI smoke tests, but the final portable audit incorrectly required the original `Invio/truststore/__init__.py` source file. The audit now checks only stable portable resources while executable smoke gates remain the runtime proof. Phase-1 TLS and Phase-2 provider-limit behavior remain unchanged. diff --git a/ROADMAP.md b/ROADMAP.md index e338697..c737864 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,6 +1,8 @@ -## Release readiness — v1.0.0.1.50.1 +## Current authoritative roadmap state — v1.0.0.1.50.1 -Phase 4 Deterministic Dynamic Tags V1 in `v1.0.0.1.50` is now CI-accepted on exact commit `b87b412413f8788656c89b3b97a487d855d10d5f` by GitHub Actions run `32109507918`. The run passed Linux tests, native Windows **642/642** regression, wheel/P14, PySide6/keyring/resource smoke, Nuitka OneDir, credential/TLS smokes, WiX MSI lifecycle, release-payload audit, and artifact upload. `v1.0.0.1.50.1` does not reopen any functional phase; it synchronizes release readiness and version identity only. +Invio `v1.0.0.1.50.1` is the current published product release (published 2026-08-18). Phase 1–4 runtime behavior remains accepted/frozen, operational SQLite is schema **v7**, and the published release lineage remains unchanged. Repository-maintenance Phase-01 (F-001/F-002) and Phase-02 (F-003/F-004) were completed afterward as non-functional source/repository corrections; they do not advance the product roadmap or change runtime behavior. + +All version-specific sections below are historical planning/acceptance records for their named versions. Terms such as “candidate”, “baseline”, or “next phase” inside those records describe their point-in-time state and are not current roadmap status. ## Phase 4 — Deterministic Dynamic Tags V1 — v1.0.0.1.50 ACCEPTED BASELINE @@ -72,35 +74,35 @@ The approved Accounts-page **Compact Flat Account Table & Semantic Status UI** i The approved Tasks-page New Task modal compact UI redesign is the only v1.0.0.1.48.4 scope. It does not introduce a new production phase or alter the existing provider/task/storage roadmap. -## Current CI/CD Stabilization Candidate — v1.0.0.1.48.3 +## Historical CI/CD Stabilization Candidate — v1.0.0.1.48.3 Parent Official Baseline: `Invio_v1.0.0.1.48.02_CL_FIx_Baseline.zip`. Scope is limited to GitHub CI/test/build/release stabilization and required version/documentation synchronization. The correction restores the established public/private repository-contract boundary; it does not advance production phases or modify application behavior. A post-push GitHub Actions run remains the authoritative Windows OneDir/MSI/artifact confirmation gate. -## Current Hotfix Candidate — v1.0.0.1.48.02 +## Historical Hotfix Candidate — v1.0.0.1.48.02 Parent Official Baseline: `v1.0.0.1.48.01`. Scope is limited to the global app-owned `QMessageBox` / popup lifecycle regression and real PySide6 interaction regression coverage. Production/provider roadmap ordering and business/runtime phase status are unchanged. -## Current Hotfix Candidate — v1.0.0.1.48.01 +## Historical Hotfix Candidate — v1.0.0.1.48.01 Parent Official Baseline: `v1.0.0.1.48.0`. This candidate fixes only the Tasks `Close Task` confirmation boundary. Production/provider roadmap ordering and phase status are unchanged. -## Current UI Candidate — v1.0.0.1.48.0 +## Historical UI Candidate — v1.0.0.1.48.0 Parent Official Baseline: `v1.0.0.1.47.0`. This candidate is limited to custom Main/Dialog chrome spacing, app-owned dialog visual separation and duplicate dialog-title cleanup. Runtime/provider/business roadmap ordering is unchanged. -## Current UI Candidate — v1.0.0.1.47.0 +## Historical UI Candidate — v1.0.0.1.47.0 Parent Official Baseline: `v1.0.0.1.46.0`. This candidate is limited to the owner-approved Vib Tools desktop design-system refinement. Runtime/provider/business roadmap ordering is unchanged. -**Current owner-frozen baseline:** `Invio v1.0.0.1.45.0`. **Active approved UI candidate:** `v1.0.0.1.46.0 — custom Main Window and app-owned Dialog title bars only`. Provider/runtime roadmap status is unchanged. +**Historical owner-frozen baseline at that point:** `Invio v1.0.0.1.45.0`. **Historical approved UI candidate:** `v1.0.0.1.46.0 — custom Main Window and app-owned Dialog title bars only`. Provider/runtime roadmap status is unchanged. # Roadmap -**Current owner-frozen UI baseline:** `Invio v1.0.0.1.44.0`. **Active approved UI candidate:** `Invio v1.0.0.1.45.0 — Providers Page transient-window/card-layout fix only`. Production/runtime phase status is inherited unchanged; this UI candidate does not reopen or advance any provider/runtime phase. +**Historical owner-frozen UI baseline at that point:** `Invio v1.0.0.1.44.0`. **Historical approved UI candidate:** `Invio v1.0.0.1.45.0 — Providers Page transient-window/card-layout fix only`. Production/runtime phase status is inherited unchanged; this UI candidate does not reopen or advance any provider/runtime phase. -Current owner-frozen Official UI Baseline: **Invio v1.0.0.1.41 — Providers Page UI/UX baseline**. The first production-release lineage remains rooted in v1.0.0.1.40.2. +Historical owner-frozen Official UI Baseline at that point: **Invio v1.0.0.1.41 — Providers Page UI/UX baseline**. The first production-release lineage remains rooted in v1.0.0.1.40.2. -Active approved UI candidate: **Invio v1.0.0.1.41.1 — Providers Page final UI polish only**. Production/runtime phase status remains inherited unchanged; this hotfix does not reopen or advance any provider/runtime phase. +Historical approved UI candidate: **Invio v1.0.0.1.41.1 — Providers Page final UI polish only**. Production/runtime phase status remains inherited unchanged; this hotfix does not reopen or advance any provider/runtime phase. Owner acceptance on 2026-08-10 records a successful real Odoo end-to-end invoice delivery path through the frozen P13 external-provider contract and accepts the green Windows distribution pipeline as the P14 native packaging gate. **P14 is COMPLETE by explicit owner production acceptance.** P11 remains the separate Refrens-specific live acceptance phase and is **IMPLEMENTED / LIVE ACCEPTANCE DEFERRED (non-blocking for v1.0.0.1.40.2)** because Refrens API mail is rejected by the provider with `HTTP 400: Not allowed to send mail`. diff --git a/docs/developer/ACTUAL_IMPLEMENTATION_STATUS.md b/docs/developer/ACTUAL_IMPLEMENTATION_STATUS.md index 9836c01..4df7fa9 100644 --- a/docs/developer/ACTUAL_IMPLEMENTATION_STATUS.md +++ b/docs/developer/ACTUAL_IMPLEMENTATION_STATUS.md @@ -1,3 +1,14 @@ +# Current authoritative implementation state + +- Product release: `v1.0.0.1.50.1` (published 2026-08-18). +- Application/wheel version: `1.0.0.1.50.1`. +- Operational SQLite schema: **v7**. +- Phase 1–4 runtime behavior: implemented/accepted and frozen. +- Repository-maintenance Phase-01 (F-001/F-002): complete; no runtime feature change. +- Repository-maintenance Phase-02 (F-003/F-004): complete; no runtime feature change. + +Historical version sections below preserve point-in-time implementation evidence. Their candidate/baseline wording is historical and does not override this current state. + ## v1.0.0.1.50.1 — Phase 1–4 release readiness **Status: RELEASE-READINESS MAINTENANCE / RUNTIME FROZEN.** Phase 4 v1.0.0.1.50 at commit `b87b412413f8788656c89b3b97a487d855d10d5f` passed GitHub Actions run `32109507918`, including native Windows **642/642 PASS**, wheel/P14, compiled PySide6/keyring, Nuitka startup, credential and Windows-native TLS smokes, WiX MSI lifecycle, P14 release-payload audit, and artifact upload. Phase-1 TLS, Phase-2 provider terminal-stop semantics, Phase-3 sending controls and Phase-4 Dynamic Tags V1 remain unchanged in this hotfix. @@ -76,29 +87,29 @@ Status tone classification, display markers and table status-cell composition ar **IMPLEMENTED LOCALLY / REMOTE CONFIRMATION PENDING:** GitHub Actions run `31516505105` proves the Linux Qt dependency correction and real PySide6 popup runtime tests are working on both Linux and Windows. The remaining 21 failures are repository-contract failures caused by a partially unignored private `project/` tree. `v1.0.0.1.48.3` restores the established public/private test boundary: public CI no longer materializes `project/`, while a full private baseline continues to validate private records conditionally. Runtime/UI/business/provider/storage behavior is unchanged. A new pushed v1.48.3 run is required before claiming remote Windows wheel/Nuitka/MSI/artifact completion. -## v1.0.0.1.47.0 UI Candidate Status +## v1.0.0.1.47.0 Historical UI Candidate Status **Scope:** UI/UX only. The single-header shell, grouped SVG sidebar, standardized frameless dialog shell, centralized component states and approved Accounts/Customer Lists/Invoice Templates presentation are implemented. Provider runtime, storage, task execution, settings and business logic remain unchanged. -## v1.0.0.1.46.0 candidate +## v1.0.0.1.46.0 historical candidate Window-chrome scope implemented: custom MainTitleBar and DialogTitleBar; all provider/runtime/storage/business phases retain their prior status. # Actual Implementation Status -## v1.0.0.1.45.0 candidate +## v1.0.0.1.45.0 historical candidate Owner-frozen parent: `v1.0.0.1.44.0`. Candidate scope is limited to the Providers Page transient top-level-card prevention and compact Available/Verified placement/card-height correction. Provider/runtime/storage/business architecture remains unchanged. -## v1.0.0.1.44.0 candidate +## v1.0.0.1.44.0 historical candidate Parent baseline `v1.0.0.1.43.0` remains architecturally frozen. Candidate scope is limited to static intro/subtitle rendering plus version/tests/docs; no runtime/business/persistence architecture is reopened. -**Current UI baseline/candidate:** `Invio v1.0.0.1.44.0` owner-frozen baseline → `Invio v1.0.0.1.45.0` Providers Page transient-window/card-layout fix candidate. Provider/runtime/storage/business behavior unchanged. +**Historical UI baseline/candidate at that point:** `Invio v1.0.0.1.44.0` owner-frozen baseline → `Invio v1.0.0.1.45.0` Providers Page transient-window/card-layout fix candidate. Provider/runtime/storage/business behavior unchanged. -**Official Production Baseline:** `Invio v1.0.0.1.40.2` -**Current UI baseline/candidate:** `Invio v1.0.0.1.41` owner-frozen baseline → `Invio v1.0.0.1.41.1` Providers Page final-polish candidate; provider/runtime/storage behavior unchanged. +**Historical first production baseline:** `Invio v1.0.0.1.40.2` +**Historical UI baseline/candidate at that point:** `Invio v1.0.0.1.41` owner-frozen baseline → `Invio v1.0.0.1.41.1` Providers Page final-polish candidate; provider/runtime/storage behavior unchanged. **Production status:** **ACCEPTED / FIRST PRODUCTION RELEASE** **P14:** **COMPLETE BY EXPLICIT OWNER PRODUCTION ACCEPTANCE** **P11 Refrens:** **IMPLEMENTED / LIVE ACCEPTANCE DEFERRED — NON-BLOCKING FOR v1.0.0.1.40.2** @@ -124,7 +135,7 @@ Parent baseline `v1.0.0.1.43.0` remains architecturally frozen. Candidate scope | Refrens normal Task sending | BLOCKED externally / LIVE ACCEPTANCE DEFERRED | Authentication and invoice creation succeed live; the documented API email endpoint currently returns HTTP 400 `Not allowed to send mail`, so provider-side API mail permission/capability must be resolved before live acceptance | | Odoo external provider invoice sending | LIVE PRODUCTION ACCEPTED | Owner-confirmed Odoo Provider v1.0.0 end-to-end invoice creation/posting/email send through P13 | | Real Add Account API Test | WORKING by built-in/external providers | Stripe/Refrens verification remains real; Agiled now performs the verified Bearer safe-read `GET https://api.agiled.ai/public/v1/me` on the existing dedicated dialog `QThread` | -| Durable Accounts metadata | WORKING | Current SQLite schema v5 retains IDs/provider/name/mode/status/verification health/credential reference; account-health columns originated in schema v2 | +| Durable Accounts metadata | WORKING | Current SQLite schema v7 retains the existing Account identity/status/verification/credential-reference contract; account-health columns originated in schema v2 and later schema additions remain additive. | | Protected provider credentials | WORKING / NATIVE DISTRIBUTION ACCEPTED | `keyring` only; no plaintext fallback; Windows compiled credential smoke is part of the accepted P14 distribution evidence | | Durable Customer Lists | WORKING | Ordered customer records restore after restart; email mandatory, optional explicit name/country | | Durable Invoice Templates | WORKING | Template fields/items/terms restore; Decimal values stored as text | @@ -135,7 +146,7 @@ Parent baseline `v1.0.0.1.43.0` remains architecturally frozen. Candidate scope | Worker/network reliability | WORKING | P08 structured retry classification, bounded retry/backoff/jitter, Retry-After, explicit timeout policy and safe asynchronous shutdown; v1.0.0.1.24 corrects truncated-body/TLS-close transient classification | | Retry Failed / Resume Remaining in current session | WORKING | P07 uses exact ProviderRuntime failed/pending sets and immutable P05 ordering | | Retry Failed / Resume Remaining after app restart | WORKING | P10 uses durable latest recipient outcomes and exact attempted-account binding; unsupported historical evidence fails closed | -| Recipient delivery ledger/provider IDs | WORKING | Schema v5 stores runs, per-run recipients, operations, attempts, idempotency evidence, provider customer/invoice IDs and sanitized errors | +| Recipient delivery ledger/provider IDs | WORKING | Current schema v7 retains the P10 delivery-ledger tables introduced in schema v5: runs, per-run recipients, operations, attempts, idempotency evidence, provider customer/invoice IDs and sanitized errors. | | Recipient reports / structured logs / safe exports | WORKING | P12 uses the P10 ledger for recipient support rows, structured privacy-redacted Live Logs, atomic formula-safe CSV/text exports and closed-history retention controls | | Settings persistence | WORKING | Existing non-sensitive JSON remains separate from P02 storage | @@ -160,7 +171,7 @@ Parent baseline `v1.0.0.1.43.0` remains architecturally frozen. Candidate scope - Account reservation creation is transactional with Task creation. Task close transactionally deletes the Task and releases reservations. - Template parent/items/terms and customer email replacement are committed transactionally. - Startup integrity/schema validation rejects corrupt, unknown unversioned, and newer unsupported schemas without silently replacing them. -- Existing supported schema-v0/v1/v2/v3/v4 databases use the existing WAL-aware pre-migration backup path before advancing to current schema v5. +- Existing supported schema-v0/v1/v2/v3/v4 databases use the existing WAL-aware pre-migration backup path before advancing through the supported migration chain; schema v5 was the current target for this historical P02/P10 record. - Missing/unreadable protected credentials leave Account metadata visible but force runtime status `Not Verified`, preserving P01 Task gates. - Previously active Tasks are not automatically resumed after process restart. - Persistence failures are translated into existing `StateError`/user-facing handling; active task persistence failure requests WorkerManager stop. @@ -338,7 +349,7 @@ The internal packaged-provider adapter registry is **WORKING**. Dynamic arbitrar ## P10 status - v1.0.0.1.27 -**WORKING:** SQLite schema v5; exactly three durable delivery-ledger tables; distinct execution Run IDs; write-ahead operation starts; P08 attempt history; exact Stripe Task-derived idempotency evidence; provider customer/invoice IDs when returned; sanitized durable errors; final Pending/Succeeded/Failed/Uncertain outcomes; interrupted-run recovery; durable aggregate reconciliation; restart-safe Resume Remaining / Retry Failed; P09 exact attempted-account binding across restart; historical ledger retention after Close Task. +**WORKING:** P10 introduced the delivery ledger in SQLite schema v5; current schema v7 retains exactly three durable delivery-ledger tables; distinct execution Run IDs; write-ahead operation starts; P08 attempt history; exact Stripe Task-derived idempotency evidence; provider customer/invoice IDs when returned; sanitized durable errors; final Pending/Succeeded/Failed/Uncertain outcomes; interrupted-run recovery; durable aggregate reconciliation; restart-safe Resume Remaining / Retry Failed; P09 exact attempted-account binding across restart; historical ledger retention after Close Task. **FAIL-CLOSED:** pre-P10 non-pristine Tasks do not receive invented delivery history; unsupported or inconsistent durable continuation evidence is rejected. A required pre-request ledger write failure sends nothing; a post-provider ledger result failure stops before further side effects and leaves observable write-ahead evidence for restart recovery. diff --git a/docs/index.md b/docs/index.md index 53c52ce..58df42f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,24 +1,26 @@ -## v1.0.0.1.50.1 release readiness +## Current authoritative documentation state — v1.0.0.1.50.1 -The owner-frozen v1.0.0.1.50 Phase-4 source at commit `b87b412413f8788656c89b3b97a487d855d10d5f` passed GitHub Actions run `32109507918`, including native Windows **642/642** regression and the complete Windows distribution chain. v1.0.0.1.50.1 synchronizes that accepted evidence with current release/version records without changing Phase 1–4 behavior. +Invio `v1.0.0.1.50.1` is the current published product release (published 2026-08-18). Application/wheel version remains `1.0.0.1.50.1`, operational SQLite remains schema **v7**, and Phase 1–4 runtime behavior remains frozen. Repository-maintenance Phase-01 (F-001/F-002) and Phase-02 (F-003/F-004) were completed afterward without changing runtime behavior, provider contracts, UI/UX, schema, version, or published release artifacts. + +The version sections below are historical records for their named releases/candidates; historical “current” or “candidate” language must not be interpreted as an alternate present-day baseline. ## Accepted Phase-4 baseline — v1.0.0.1.50 Deterministic Dynamic Tags V1 is implemented as a provider-neutral host feature. Exact tags: `#NAME#`, `#EMAIL#`, `#R5#`, `#R11#`, `#DATE#`, `#DATE-NAME#`, `#YAAR#`. Unknown tags stay literal. Date tags use the frozen Task-creation UTC reference; numeric tags are stable for one Task+recipient across retry/resume/restart. Supported target fields are Settings Default Customer Name and Invoice Template Memo, Footer, Customer Note, Terms, and Item Description. Operational schema is v7. No new UI page or provider-specific tag is introduced. -## Current baseline candidate — v1.0.0.1.49.9 +## Historical baseline candidate — v1.0.0.1.49.9 v1.0.0.1.49.9 retains the complete v1.0.0.1.49.8 Phase-3 Sending Scheduler / Retry / Delay feature set and fixes only the Windows SQLite connection lifecycle in its schema-migration regression fixture. No application workflow, Settings contract, provider behavior, task execution or database schema changed. -## Current version — v1.0.0.1.49.8 +## Historical version — v1.0.0.1.49.8 Phase 3 exposes bounded sending controls while preserving host/provider ceilings. New Task snapshots freeze timeout, automatic-attempt count, additional recipient delay and any approved lower per-account provider rate. SQLite schema v6 makes the captured contract restart-safe. Stripe remains capped at 20 req/s/account, Refrens at 1 req/s/account, and Odoo remains without a declared numeric scheduler ceiling. -## Current version — v1.0.0.1.49.7 +## Historical version — v1.0.0.1.49.7 v1.49.7 is a narrow CI/release-audit correction over the verified Phase-1/Phase-2 implementation. Windows native TLS, provider fatal-limit handling, Odoo v1.0.1, Task/WorkerManager, storage and UI workflows are unchanged. -## Current version — v1.0.0.1.49.6 +## Historical version — v1.0.0.1.49.6 Phase 2 adds the provider fatal-limit circuit breaker and Odoo v1.0.1 safe mail-evidence handling. Phase-1 Windows native TLS remains enabled; Phase 3/4 are deferred. @@ -26,7 +28,7 @@ Phase 2 adds the provider fatal-limit circuit breaker and Odoo v1.0.1 safe mail- Phase 1 corrects Windows/RDP provider TLS trust compatibility by using the native Windows certificate trust store in the shared ProviderRuntime transport. Certificate and hostname verification remain mandatory. -## Current version — v1.0.0.1.49.4 +## Historical version — v1.0.0.1.49.4 Provider IVX Package System V1 remains the active provider-distribution contract. v1.49.4 corrects native Windows raw ZIP path validation, additive provider-logo lookup compatibility, canonical/portable archive-path validation, unsupported-compression error containment, optional PNG safety checks and IVX builder publication atomicity. No provider API/send or application business workflow changed. @@ -34,11 +36,11 @@ Provider IVX Package System V1 remains the active provider-distribution contract Provider IVX Package System V1 adds secure single-file external provider distribution while retaining all existing provider execution and legacy manifest-loading contracts. See the Provider Guide and Provider Manifest reference for IVX Format v1. -## Current release candidate — v1.0.0.1.49.2 +## Historical release candidate — v1.0.0.1.49.2 v1.49.2 is a narrow compatibility correction on the frozen Provider Easy Onboarding V1 baseline. Existing Browser-OAuth-only runtime collaborators can open Add/Edit Account without implementing Easy Onboarding methods; the real Invio `ProviderRuntime` continues to expose the complete Quick Connect flow unchanged. -## Current release candidate — v1.0.0.1.49.1 +## Historical release candidate — v1.0.0.1.49.1 This hotfix adds optional browser-based provider authorization with persistent protected refresh credentials and corrects the Windows MSI Start Menu launch entry. Existing provider sending and application business workflows remain frozen. @@ -50,19 +52,19 @@ Providers and Settings now use the frozen compact header spacing consistently. I Customer Lists now follows the compact two-panel design, and applicable pages use the same compact page/section header hierarchy. Runtime/business behavior remains unchanged. -## Current UI Correction — v1.0.0.1.48.8 +## Historical UI Correction — v1.0.0.1.48.8 The Accounts `STATUS` column now honors the shared canonical status badge size hint instead of using a fixed 132px width. This is a runtime geometry correction only; status semantics and workflows are unchanged. -## Current UI Update — v1.0.0.1.48.7 +## Historical UI Update — v1.0.0.1.48.7 Global status rendering now uses one shared semantic component path. Duplicate raw status text underneath table badges is removed without changing backend status values or workflows. -## Current UI Update — v1.0.0.1.48.6 +## Historical UI Update — v1.0.0.1.48.6 Accounts retain the v1.48.5 flat table and compact controls with rebalanced columns, approved compact semantic badges, a fully contained Action column, and each existing row menu bounded to the Invio-window/current-screen safe region. -## Current UI Update — v1.0.0.1.48.5 +## Historical UI Update — v1.0.0.1.48.5 Accounts now use one compact flat account table with one-row search/provider/status controls, semantic status badges, existing pagination, and per-row `⋯` actions. No account/backend workflow changed. @@ -82,11 +84,11 @@ The current candidate repairs all existing Invio-owned warning/error/info/confir The current candidate fixes only the Tasks-page `Close Task` confirmation path on Windows while preserving the existing backend close/release engine and every unrelated workflow. -## v1.0.0.1.48.0 Current UI Candidate +## v1.0.0.1.48.0 Historical UI Candidate Parent baseline: `v1.0.0.1.47.0`. The candidate polishes only custom Main/Dialog chrome and app-owned dialog title/separation presentation. See `release-notes/1.0.0.1.48.0.md`. -## Current UI Candidate — v1.0.0.1.47.0 +## Historical UI Candidate — v1.0.0.1.47.0 The current UI candidate builds on the owner-frozen `v1.0.0.1.46.0` baseline and standardizes the application shell, navigation, app-owned dialogs and shared visual states without changing business workflows. @@ -96,18 +98,18 @@ Custom branded frameless chrome replaces the native white Main Window and applic # Invio Documentation -Current UI baseline/candidate chain: **v1.0.0.1.44.0 is owner-frozen; v1.0.0.1.45.0 is the Providers Page transient-window/card-layout fix candidate.** The candidate prevents provider cards from becoming transient top-level windows before grid re-parenting and relocates/compacts the existing Available/Verified mark; runtime/business behavior is unchanged. +Historical UI baseline/candidate chain at that point: **v1.0.0.1.44.0 is owner-frozen; v1.0.0.1.45.0 is the Providers Page transient-window/card-layout fix candidate.** The candidate prevents provider cards from becoming transient top-level windows before grid re-parenting and relocates/compacts the existing Available/Verified mark; runtime/business behavior is unchanged. - `release-notes/1.0.0.1.45.0.md` - Providers Page transient-window/card-layout fix candidate. -Current UI baseline/candidate chain: **v1.0.0.1.42.0 is owner-frozen; v1.0.0.1.43.0 is the Global Data Tables + Lists + Fonts candidate.** The candidate adds compact in-memory search/filter/pagination and data-surface presentation only; runtime/provider/storage/task business behavior is unchanged. +Historical UI baseline/candidate chain at that point: **v1.0.0.1.42.0 is owner-frozen; v1.0.0.1.43.0 is the Global Data Tables + Lists + Fonts candidate.** The candidate adds compact in-memory search/filter/pagination and data-surface presentation only; runtime/provider/storage/task business behavior is unchanged. - `release-notes/1.0.0.1.43.0.md` - Global Data Tables + Lists + Fonts candidate. -Official Production Baseline: **v1.0.0.1.40.2 — FIRST PRODUCTION RELEASE**. Owner-confirmed Odoo Provider v1.0.0 end-to-end invoice sending is the production-certified live provider path. P14 is complete by explicit owner acceptance; Refrens P11 live email acceptance is deferred/non-blocking. +Historical first production baseline: **v1.0.0.1.40.2 — FIRST PRODUCTION RELEASE**. Owner-confirmed Odoo Provider v1.0.0 end-to-end invoice sending is the production-certified live provider path. P14 is complete by explicit owner acceptance; Refrens P11 live email acceptance is deferred/non-blocking. -Current UI baseline/candidate chain: **v1.0.0.1.41 is the owner-frozen Providers Page UI baseline; v1.0.0.1.41.1 is the final Providers Page polish candidate.** v1.41.1 adds search/filter, real provider logos and simplified card presentation only. Runtime/provider/storage/threading behavior remains unchanged. +Historical UI baseline/candidate chain at that point: **v1.0.0.1.41 is the owner-frozen Providers Page UI baseline; v1.0.0.1.41.1 is the final Providers Page polish candidate.** v1.41.1 adds search/filter, real provider logos and simplified card presentation only. Runtime/provider/storage/threading behavior remains unchanged. Invio is a Vib Tools desktop application for provider-managed invoice automation. Current workflow: @@ -174,20 +176,20 @@ P08 Worker and Network Reliability is complete. Invio now classifies transient/p P08 remains complete. The forensic correction extends the transient-disconnect classifier to truncated HTTP response bodies and TLS EOF/clean-close interruptions, while retaining known HTTP status and Retry-After semantics when an error body is incomplete. Retry count/backoff, provider operations, shutdown architecture and all P09+ behavior remain unchanged. Production progress remains 8/14; P09 is next. -## v1.0.0.1.25 current baseline +## v1.0.0.1.25 historical baseline P09 adds conservative multi-account scheduling without changing the frozen round-robin primary mapping. Stripe Task traffic is paced per account, temporary account/provider health is runtime-only, eligible failover is restricted to unattempted recipients, and attempted recipients are protected from cross-account replay. P10 persistence/recovery remains unimplemented. -## v1.0.0.1.26 current baseline +## v1.0.0.1.26 historical baseline The P09 runtime remains unchanged. This verification correction fixes the public CI repository-contract boundary so tracked documentation is mandatory in GitHub Actions while intentionally private Git-ignored `project/` records are only checked when available in a full private baseline. Production progress remains 9/14 and P10 remains next. -## v1.0.0.1.27 current baseline +## v1.0.0.1.27 historical baseline P10 advances SQLite to schema v5 and adds durable execution runs, per-run recipient outcomes, and provider-operation evidence. Supported Stripe Task operations are write-ahead recorded before transport, interrupted mutating operations recover as `Uncertain`, and restart-safe Resume Remaining / Retry Failed now use the durable ledger. P09 account binding, P08 retry/idempotency, the existing page inventory, Refrens P11 gate and Agiled fail-close remain unchanged. -## v1.0.0.1.28 current baseline +## v1.0.0.1.28 historical baseline P10 remains complete and schema remains v5. This verification correction ensures unresolved mutating ambiguity survives across attempts/runs until exact same-stage/same-idempotency successful evidence reconciles it. Production progress remains **10/14**; P11 remains the next separately approval-gated phase. @@ -236,15 +238,15 @@ The current source/build baseline fixes the GitHub Windows pipeline's false WiX ## v1.0.0.1.38 WiX release inventory correction v1.38 preserves the existing Windows distribution design and suppresses WiX's default `.wixpdb` debug sidecar so the checksum manifest and distribution audit operate on the same approved portable/MSI/wheel payload set. P14 remains certification pending. -## Current v1.0.0.1.39 correction candidate +## Historical v1.0.0.1.39 correction candidate `v1.0.0.1.38` remains the Official released parent baseline. `v1.0.0.1.39` is a pre-release correction for the owner-observed compiled protected-credential storage failure after a successful Refrens API Test. It preserves the existing keyring/security/provider/storage architecture and adds explicit compiled keyring packaging plus OneDir/MSI CredentialStore round-trip verification. Do not tag/release the candidate until owner source/live and compiled-artifact validation pass. -## Current v1.0.0.1.40 live-correction candidate +## Historical v1.0.0.1.40 live-correction candidate Owner-frozen parent baseline is v1.0.0.1.39. v1.40 is limited to the live Refrens `terms` payload correction, email-only customer defaults, the reported dark list/menu/table surfaces, and owner app icon wiring. Do not tag/release until local source Refrens invoice/email acceptance and subsequent non-tagged compiled-artifact acceptance both pass. -## Current v1.0.0.1.40.1 error-fix candidate +## Historical v1.0.0.1.40.1 error-fix candidate The owner-frozen v1.40 baseline now proves real Refrens invoice creation but exposed a separate email-trigger gap. v1.40.1 uses Refrens' explicit post-create invoice-email endpoint, restores Settings to the shared frozen Vib Tools form/card spacing and typography, and removes the obsolete custom Nuitka keyring package config from CI. Agiled stays fail-closed; P11/P14 and production certification remain pending. @@ -253,7 +255,7 @@ The owner-frozen v1.40 baseline now proves real Refrens invoice creation but exp Agiled Account API Test is now executable against the exact current `GET https://api.agiled.ai/public/v1/me` Bearer endpoint. Agiled Task sending is still unavailable because the supplied OpenAPI does not define an invoice email/send operation or field-level invoice mutation schema. Refrens live API mail remains blocked by the provider response `HTTP 400: Not allowed to send mail`; Invio logs the provider HTTP status explicitly and does not convert the rejection into success. -## Current production baseline +## Historical production baseline record **Invio v1.0.0.1.40.2** is the first owner-accepted production release. Odoo Provider v1.0.0 is the live end-to-end accepted invoice-send path. P14 is complete by explicit owner production acceptance; Refrens P11 live mail acceptance remains deferred/non-blocking and is not claimed as certified delivery. diff --git a/docs/release-notes/1.0.0.1.50.1.md b/docs/release-notes/1.0.0.1.50.1.md index 08dbd05..5735ca5 100644 --- a/docs/release-notes/1.0.0.1.50.1.md +++ b/docs/release-notes/1.0.0.1.50.1.md @@ -14,11 +14,13 @@ GitHub Actions run `32109507918` executed the exact parent commit and completed - Synchronize current documentation/status from “candidate / CI pending” to the now-verified v1.0.0.1.50 acceptance state. - Remove the tracked trailing whitespace from `PATCH_MANIFEST_v1.0.0.1.50.md`. -- Advance release identity only to application/wheel `1.0.0.1.50.1`, PE `1.0.1.5001`, MSI `1.1.5001`, future tag `v1.0.0.1.50.1`. +- Advance release identity only to application/wheel `1.0.0.1.50.1`, PE `1.0.1.5001`, MSI `1.1.5001`, and tag `v1.0.0.1.50.1`. - Add release-readiness verification/freeze records and current release contract coverage. ## Frozen behavior No production behavior is changed. Phase-1 native TLS trust and fail-closed certificate verification, Phase-2 provider fatal-limit circuit breaker, Phase-3 timeout/retry/delay/rate controls, Phase-4 Dynamic Tags V1, schema v7, provider/Odoo contracts, Task state machine, WorkerManager/QThread architecture, delivery ledger, CredentialStore, OAuth/Easy Onboarding, ProviderManager/IVX, application pages and unrelated UI/UX remain unchanged. -The Git tag is not created by this source correction. Exact v1.0.0.1.50.1 post-push non-tag CI remains the final gate before owner tag/release publication. +## Published release + +Tag `v1.0.0.1.50.1` and GitHub Release `Invio v1.0.0.1.50.1` were published on 2026-08-18 with the Python wheel, Windows x64 portable ZIP, Windows x64 MSI, and release `SHA256SUMS.txt`. Later repository-maintenance phases do not modify those published release artifacts or reopen Phase 1–4 runtime behavior. diff --git a/tests/test_documentation_truth.py b/tests/test_documentation_truth.py new file mode 100644 index 0000000..5787220 --- /dev/null +++ b/tests/test_documentation_truth.py @@ -0,0 +1,103 @@ +from __future__ import annotations + +import re +import tomllib +import unittest +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +CURRENT_DOCS = ( + ROOT / "README.md", + ROOT / "ROADMAP.md", + ROOT / "docs" / "index.md", + ROOT / "docs" / "developer" / "ACTUAL_IMPLEMENTATION_STATUS.md", +) + + +def _text(path: Path) -> str: + return path.read_text(encoding="utf-8") + + +def _version() -> str: + with (ROOT / "pyproject.toml").open("rb") as handle: + return tomllib.load(handle)["project"]["version"] + + +def _schema_version() -> int: + match = re.search( + r"^DOMAIN_SCHEMA_VERSION\s*=\s*(\d+)\s*$", + _text(ROOT / "src" / "core" / "storage" / "schema.py"), + re.MULTILINE, + ) + if match is None: + raise AssertionError("DOMAIN_SCHEMA_VERSION source-of-truth is missing") + return int(match.group(1)) + + +class DocumentationTruthTests(unittest.TestCase): + def test_current_release_lifecycle_is_truthful(self) -> None: + version = _version() + note = _text(ROOT / "docs" / "release-notes" / f"{version}.md") + self.assertIn(f"Tag `v{version}`", note) + self.assertIn("published on 2026-08-18", note) + self.assertIn("Windows x64 MSI", note) + lowered = note.lower() + self.assertNotIn("tag is not created", lowered) + self.assertNotIn("before owner tag/release publication", lowered) + + def test_current_release_changelog_has_no_future_tag_claim(self) -> None: + version = _version() + changelog = _text(ROOT / "CHANGELOG.md") + marker = f"## v{version}" + start = changelog.index(marker) + next_heading = changelog.find("\n## ", start + len(marker)) + section = changelog[start:] if next_heading < 0 else changelog[start:next_heading] + self.assertIn(f"tag `v{version}`", section) + self.assertIn("published on 2026-08-18", section) + self.assertNotIn("future tag", section.lower()) + + def test_current_facing_docs_have_one_authoritative_current_state(self) -> None: + version = _version() + banned_heading = re.compile( + r"^#{1,4}\s+Current\s+.*v1\.0\.0\.1\.(?!50\.1(?:\s|$))", + re.MULTILINE | re.IGNORECASE, + ) + for path in CURRENT_DOCS: + content = _text(path) + with self.subTest(path=path.relative_to(ROOT)): + self.assertEqual(content.lower().count("current authoritative"), 1) + self.assertIn(version, content.splitlines()[0:20].__str__()) + self.assertIsNone(banned_heading.search(content)) + + def test_current_docs_match_version_and_schema_source_of_truth(self) -> None: + version = _version() + schema = _schema_version() + status = _text(ROOT / "docs" / "developer" / "ACTUAL_IMPLEMENTATION_STATUS.md") + readme = _text(ROOT / "README.md") + self.assertIn(f"Application/wheel version: `{version}`", status) + self.assertIn(f"Operational SQLite schema: **v{schema}**", status) + self.assertIn(f"schema **v{schema}**", readme) + summary_start = status.index("## Current Summary") + next_section = status.index("\n## ", summary_start + len("## Current Summary")) + current_summary = status[summary_start:next_section] + self.assertNotIn("Current SQLite schema v5", current_summary) + self.assertIn(f"Current SQLite schema v{schema}", current_summary) + + def test_security_policy_matches_current_implemented_boundaries(self) -> None: + security = _text(ROOT / ".github" / "SECURITY.md") + for required in ( + "There is no plaintext-file fallback", + "native Windows trust store", + "structured privacy redaction", + "explicit trust boundary", + "Signing Option C", + "Unknown Publisher", + ): + with self.subTest(required=required): + self.assertIn(required, security) + self.assertNotIn("later production roadmap phases and are not claimed", security) + + +if __name__ == "__main__": + unittest.main()