From 4b01593e9ce5562247a2cbbac491591bcbfeb3ba Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 27 Oct 2026 22:04:41 +1100 Subject: [PATCH 1/2] docs: add BR-38, cross-platform offline install (#128) Wording approved by the product owner on 27 Oct 2026. Status: Not started. Headline now 19 of 38 verified. offline-install.md points its "Ubuntu only" limit at #128. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019YPoXzBSj89ZHgw7nfTmbB --- docs/VCRM.md | 8 ++++++-- docs/offline-install.md | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/VCRM.md b/docs/VCRM.md index b9db6d8..666482e 100644 --- a/docs/VCRM.md +++ b/docs/VCRM.md @@ -84,6 +84,7 @@ Added by ART Milestone 0 (#53) and approved by the product owner on 2026-10-26. | **BR-35** | Audit events shall be append-only at database level; reports shall be filterable; exports shall neutralise spreadsheet formula injection. | ART v2, D7 | | **BR-36** | Users shall authenticate; access shall be role-based; no tenant shall read or affect another tenant's data. | ART v2, D1, ADR-0003, decision 6 | | **BR-37** | Data shall stay inside the deployment boundary, with no runtime external services, and the stack shall install offline. | ART v2, D6, decision 7 | +| **BR-38** | The platform shall install and run without internet access on Windows, macOS and Linux hosts that have a container runtime (Docker or Podman) installed. | Product owner, 27 Oct 2026; #128 | ### Out of scope (recorded for completeness) @@ -135,7 +136,7 @@ The `input_data/` loader has its own implicit requirements — verified end-to-e | BR-D4 | Duplicate primary keys in source are reported, not silently dropped | 4 (duplicate detection) | ✅ | | BR-D5 | Loaded data is browsable (sample peek) | 1 (sample rows) | ✅ | -### ART extension traceability (BR-23 to BR-37) +### ART extension and later requirements, traceability (BR-23 to BR-38) Status as assessed on 2026-10-26 at `main` 032b522. None of these is "Verified" until a test run proves it (D5). @@ -156,6 +157,7 @@ Status as assessed on 2026-10-26 at `main` 032b522. None of these is "Verified" | BR-35 | ⚠️ Partial | Export formula injection neutralised (M1: #86, `export.test.ts`); audit table still plain, no actor, no filters | DB negative tests + unit | M1, M3, M7 | | BR-36 | ⚠️ Partial | Done in M2:
• local accounts with lockout (#98, #103)
• OIDC (#105)
• per-tenant schemas, T&E tables included (#100, #104)
• role matrix in `docs/ROLES.md` (#101)

Tests: `tests/test_accounts.py`, `test_tenant_isolation.py`, `test_roles.py`, `test_oidc.py`, `test_password_reset.py`. Each failed with its control removed.
• frontend sign-in; the browser no longer holds the shared key (#115)
• password change, admin reset and break-glass reset (#117; `tests/test_password_reset.py`)

Open: the shared key still grants non-tenant access to scripts and services; security review (#112); real-IdP OIDC check (#113) | Cross-tenant negative tests; role matrix tests | M2 | | BR-37 | ⚠️ Partial | No external calls found; no automated check; no offline doc (#60) | Egress-blocked run + offline dry run | M7 | +| BR-38 | ❌ Not started | No container bundle for the application yet (`infra/Dockerfile` is the schema and evals runner only) | Offline smoke test 7/7 on Windows, macOS and Linux | #128 | --- @@ -178,9 +180,11 @@ Status as assessed on 2026-10-26 at `main` 032b522. None of these is "Verified" |--------|-------|-------------| | ✅ Verified | 19 | BR-01, BR-03, BR-04, BR-05, BR-06, BR-07, BR-08, BR-09, BR-10, BR-11, BR-12, BR-13, BR-14, BR-15, BR-16, BR-17, BR-18, BR-19, BR-20 | | ⚠️ Partial | 11 | BR-23, BR-25, BR-28, BR-29, BR-30, BR-31, BR-33, BR-34, BR-35, BR-36, BR-37 (ART, added 2026-10-26) | -| ❌ Not started | 4 | BR-24, BR-26, BR-27, BR-32 (ART, added 2026-10-26) | +| ❌ Not started | 5 | BR-24, BR-26, BR-27, BR-32 (ART, added 2026-10-26); BR-38 (added 2026-10-27) | | ⏸ Deferred by decision | 3 | BR-02, BR-21, BR-22 | +**Headline (2026-10-27):** with BR-38 added (cross-platform offline install, #128), **19 of 38 (50 %)** are verified, 3 are deferred by decision, and the other 16 are partial or not started. + **Headline (2026-10-26):** with the 15 ART requirements added, **19 of 37 (51 %)** are verified, 3 are deferred by decision, and the other 15 are partial or not started. **Headline before ART:** **19 of 22 (86 %)** business requirements are fully verified by at least one automated test condition, up from 17 of 22 (77 %). diff --git a/docs/offline-install.md b/docs/offline-install.md index 7eec83b..c08db5a 100644 --- a/docs/offline-install.md +++ b/docs/offline-install.md @@ -118,7 +118,7 @@ Once that evidence is on #60, the README can move to the "fully offline" wording sudo bash -c 'set -a; . /opt/te-migration/env; set +a; runuser -u te-app -- /opt/te-migration/venv/bin/python scripts/reset_password.py --username admin' ``` - **The API address is fixed at install.** It's written into the frontend files. To change it, re-run the install. -- **Ubuntu 24.04 x86_64 only.** Other operating systems need different packages and wheels. +- **Ubuntu 24.04 x86_64 only.** Other operating systems need different packages and wheels. An offline container bundle for Windows, macOS and Linux is tracked as #128 (BR-38). ## How it was rehearsed From e8df6d6d701a0154285aa754949d042a38758bce Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 27 Oct 2026 22:39:26 +1100 Subject: [PATCH 2/2] docs(readme): 27 Oct refresh: test count and limitations - vitest 102 -> 139 (badge, tree, test section), counted on main 4635328. - Known limitations: shared-user password reset is operator-only (#117); upload failure reasons live in the browser until M3 (#107); offline install is Ubuntu-only, cross-platform bundle tracked as #128. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019YPoXzBSj89ZHgw7nfTmbB --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 43ecd1a..b366f12 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![FastAPI](https://img.shields.io/badge/FastAPI-0.140%E2%80%930.141-009688?logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com/) [![React](https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=white)](https://react.dev/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) -[![Tests](https://img.shields.io/badge/Tests-102%20vitest%20%7C%20142%20SQL%20assertions-brightgreen)](#test-suite) +[![Tests](https://img.shields.io/badge/Tests-139%20vitest%20%7C%20142%20SQL%20assertions-brightgreen)](#test-suite) --- @@ -38,10 +38,16 @@ `API_KEY` is for scripts and services only; the browser never holds it. The API refuses to start outside `dev` without `API_KEY`. Requests that use the key reach the default schemas, not any tenant's. + Users change their own password from the header; a tenant admin can reset + members of their own tenant only. A user who belongs to more than one tenant + can be reset only by an operator with `scripts/reset_password.py` (#117). +- **Upload failure reasons:** the per-row reasons and step log for an upload + are kept in the uploading browser's Import history, not on the server; the + server keeps only the counts. Server-side storage is planned for M3 (#107). - **Rate limiting:** in-process only, so it suits a single API instance. - **Frontend audit page:** shows this browser's local import history, not the server audit log (see the naming note under Frontend Features). -- **Offline install:** procedure in `docs/offline-install.md`, rehearsed with networking off. The clean-VM dry run (#60) is still to do. +- **Offline install:** procedure in `docs/offline-install.md`, rehearsed with networking off. The clean-VM dry run (#60) is still to do. It targets Ubuntu 24.04 only; an offline container bundle for Windows, macOS and Linux is tracked as #128 (BR-38). ## For Reviewers @@ -103,7 +109,7 @@ PostgreDataMigrationAppWithCSVLoader/ │ │ ├── export.ts ← CSV / XLSX / PDF export │ │ ├── mapping-templates.ts ← saved column mapping templates │ │ └── csv-preview.ts ← CSV parsing utilities -│ ├── src/__tests__/ ← 102 vitest tests +│ ├── src/__tests__/ ← 139 vitest tests │ ├── .env.local ← VITE_API_BASE (not committed) │ └── package.json │ @@ -242,7 +248,7 @@ python -m pytest tests\test_te_loader_integration.py -v python -m pytest tests\environments\ -v ``` -### Frontend tests (102 vitest) +### Frontend tests (139 vitest) ```powershell cd csv-table-hub-main