SHA256
docs: record verified native preview and unfinished PWA parity
Replace current wrapper claims with native architecture/security/build evidence, preserve historical documents, track all thirty pages and explicit release gates, correct brand attribution and provide the twelve-section delivery report without claiming completion. Native signing remains paused and Apple application/device validation outstanding.
This commit is contained in:
1 parent
1433e1670a
commit
40a7962307
20 files changed
+813
-277
No files matched your search
@@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Begin the genuine native rebuild: Compose/SwiftUI screens, direct HTTPS API,
|
||||||
|
protected native session storage and initial auth/dashboard/task/note/shopping
|
||||||
|
flows. Archive the rejected WebView renderer and its tests. Full PWA parity is
|
||||||
|
explicitly incomplete; see `docs/native-parity.md`.
|
||||||
|
|
||||||
- Gitea workflows for the maintainer's Ubuntu pool and native M4 Pro runner,
|
- Gitea workflows for the maintainer's Ubuntu pool and native M4 Pro runner,
|
||||||
explicit SDK/KVM prerequisites, SHA-256 checkout and unsigned-only CI release builds.
|
explicit SDK/KVM prerequisites, SHA-256 checkout and unsigned-only CI release builds.
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -11,7 +11,9 @@ Add regression tests with security fixes, and demonstrate that the test fails
|
|||||||
without the fix. Do not commit build outputs, credentials, private signing keys,
|
without the fix. Do not commit build outputs, credentials, private signing keys,
|
||||||
local servers, generated fixture certificates, or production household data.
|
local servers, generated fixture certificates, or production household data.
|
||||||
|
|
||||||
Keep platform integrations native and dependencies minimal. The server owns
|
Keep all application screens native (Compose/SwiftUI), not just platform
|
||||||
|
integrations. No WebView fallback for unfinished modules; use the parity tracker
|
||||||
|
and never count archived browser tests as native evidence. Keep dependencies minimal. The server owns
|
||||||
business logic, authentication, CSRF, and authorization. Never solve compatibility
|
business logic, authentication, CSRF, and authorization. Never solve compatibility
|
||||||
by disabling TLS, accepting every origin, or copying a browser's session cookies.
|
by disabling TLS, accepting every origin, or copying a browser's session cookies.
|
||||||
Upstream prohibits frontend frameworks, bundlers, and transpilers in its own
|
Upstream prohibits frontend frameworks, bundlers, and transpilers in its own
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
# Yuvomi Mobile
|
# Yuvomi Mobile
|
||||||
|
|
||||||
Independent, community-maintained Android (Kotlin/WebView) and iOS
|
Independent native Android (Kotlin/Jetpack Compose) and iOS (SwiftUI) clients for
|
||||||
(SwiftUI/WKWebView) companions for user-owned [Yuvomi](https://github.com/ulsklyc/yuvomi)
|
user-owned [Yuvomi](https://github.com/ulsklyc/yuvomi) servers. Not affiliated with
|
||||||
servers. Not affiliated with or endorsed by upstream.
|
or endorsed by upstream.
|
||||||
|
|
||||||
**Development build - not production-ready.** See [validation status](docs/validation.md).
|
**Native rebuild in progress — not full PWA parity or production-ready.**
|
||||||
|
The previous WebView wrapper did not meet the requested native implementation.
|
||||||
|
It is archived under `legacy/` and is not the shipped application surface.
|
||||||
|
Read the [feature-by-feature parity tracker](docs/native-parity.md) and
|
||||||
|
[current validation](docs/validation.md) before installing a preview.
|
||||||
No mobile backend, advertisements, telemetry, tracking, subscriptions, or mandatory cloud.
|
No mobile backend, advertisements, telemetry, tracking, subscriptions, or mandatory cloud.
|
||||||
The configured server supplies the application and retains responsibility for its own
|
The apps render native controls and call the existing server API. The server owns
|
||||||
integrations, version checks, security and privacy.
|
authorization, recurrence, synchronization and household business rules.
|
||||||
|
|
||||||
Use a root-hosted HTTPS instance with a valid certificate, including private servers
|
Use a root-hosted HTTPS instance with a valid certificate, including private servers
|
||||||
accessible through your VPN. Custom ports are supported. HTTP and subpath deployments
|
accessible through your VPN. Custom ports are supported. HTTP and subpath deployments
|
||||||
are intentionally rejected. Enter the server on first launch; use Server settings to
|
are intentionally rejected. Enter the server on first launch; use **Mehr** to
|
||||||
reconnect or erase local browsing data and switch installations.
|
remove the native session and switch installations. The native client does not
|
||||||
|
import a browser/WebView session; sign in again after upgrading the prototype.
|
||||||
|
|
||||||
- [Architecture](docs/architecture.md)
|
- [Architecture](docs/architecture.md)
|
||||||
|
- [Native preview delivery report](docs/native-delivery-report.md)
|
||||||
- [Android build](docs/build-android.md) / [iOS build](docs/build-ios.md)
|
- [Android build](docs/build-android.md) / [iOS build](docs/build-ios.md)
|
||||||
- [Compatibility and authentication](docs/server-compatibility.md)
|
- [Compatibility and authentication](docs/server-compatibility.md)
|
||||||
- [Release process](docs/release-process.md)
|
- [Release process](docs/release-process.md)
|
||||||
|
|||||||
+53
-1
@@ -1,4 +1,56 @@
|
|||||||
# Security policy
|
# Security policy — native rebuild
|
||||||
|
|
||||||
|
**The current native client is an incomplete development preview, not an audited
|
||||||
|
release or full PWA replacement.** See [native parity](docs/native-parity.md).
|
||||||
|
|
||||||
|
Report vulnerabilities privately to the repository owner through an established
|
||||||
|
private channel. No reporting mailbox has been provided; do not invent one or put
|
||||||
|
cookies, keys, household records or exploit details into public issues. Upstream
|
||||||
|
server vulnerabilities belong in its private reporting channel.
|
||||||
|
|
||||||
|
## Current native security model
|
||||||
|
|
||||||
|
- Native Compose/SwiftUI screens call one configured HTTPS origin. System TLS
|
||||||
|
validation is mandatory and API redirects are refused. No WebView/WKWebView is
|
||||||
|
shipped as the app surface or used as a missing-feature fallback.
|
||||||
|
- Passwords and second-factor codes exist transiently for the API request; they
|
||||||
|
are not saved to preferences, keychains, logs, artifacts or application state
|
||||||
|
restoration. Server cookies, not passwords, persist the session.
|
||||||
|
- Android persists allow-listed Secure cookies with their absolute expiry in
|
||||||
|
AES-GCM ciphertext backed by AndroidKeyStore, with the origin authenticated as
|
||||||
|
additional data. iOS uses a private ephemeral URLSession jar and origin-scoped
|
||||||
|
Keychain items protected with WhenUnlockedThisDeviceOnly.
|
||||||
|
- CSRF tokens follow the upstream API protocol. Only an explicit `csrf_invalid`
|
||||||
|
rejection allows one refresh/retry. Other permission errors or ambiguous network
|
||||||
|
failures never cause automatic mutation replay. The server remains authoritative
|
||||||
|
for authorization, recurrence, reward accounting and cross-module rules.
|
||||||
|
- Reads are bounded and timed out. There is no offline mutation queue or native
|
||||||
|
remote push implementation. Missing features are documented, not simulated.
|
||||||
|
- Logout attempts remote revocation and clears the native local session. Local
|
||||||
|
server removal is not remote revocation. Old prototype WebKit data is not
|
||||||
|
imported; use OS app-data removal/reinstall to erase that legacy installation.
|
||||||
|
- Android screenshots are blocked. The iOS view is obscured while inactive. The
|
||||||
|
Android integration test temporarily permits a screenshot only of its synthetic
|
||||||
|
private fixture, restores the restriction and never uses real household data.
|
||||||
|
- The owner-authorized initial signing key is backed up outside the repository.
|
||||||
|
Four repository signing secrets exist, but signing/release changes are parked
|
||||||
|
during the native rebuild. No private key belongs in Git or downloadable CI
|
||||||
|
artifacts. Protect trusted-branch write access and isolate persistent runners.
|
||||||
|
|
||||||
|
## Mandatory gates
|
||||||
|
|
||||||
|
Native transports, secure storage, session erasure, actual Apple SDK compilation,
|
||||||
|
real-device behavior, accessibility, supported authentication flows and dependency
|
||||||
|
resolution need review and evidence before release. OIDC, file transfers, offline
|
||||||
|
storage and the remaining modules are not implemented native capabilities yet.
|
||||||
|
Advisory scans and parser/unit checks are not a guarantee that code is secure.
|
||||||
|
|
||||||
|
The superseded prototype policy is retained below as historical context only;
|
||||||
|
it must not be used to claim capabilities of the native rebuild.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Historical WebView prototype policy
|
||||||
|
|
||||||
**Development software: no production-readiness claim.** Only the current
|
**Development software: no production-readiness claim.** Only the current
|
||||||
development branch is maintained; no stable mobile release exists yet.
|
development branch is maintained; no stable mobile release exists yet.
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
Yuvomi Mobile is an independent community contribution, not an official Yuvomi
|
Yuvomi Mobile is an independent community contribution, not an official Yuvomi
|
||||||
product. Yuvomi's name identifies the server with which it interoperates.
|
product. Yuvomi's name identifies the server with which it interoperates.
|
||||||
Visual color values follow upstream DESIGN.md. No upstream logo is redistributed.
|
Native design-token mappings follow upstream DESIGN.md/styles. The native
|
||||||
|
three-circle brand mark is redrawn from upstream's published brand geometry and
|
||||||
|
colors (`public/utils/brand-mark.js` and `docs/logo.svg`); its MIT attribution is
|
||||||
|
preserved below. No affiliation or trademark ownership is implied.
|
||||||
|
|
||||||
Upstream Yuvomi: https://github.com/ulsklyc/yuvomi
|
Upstream Yuvomi: https://github.com/ulsklyc/yuvomi
|
||||||
|
|
||||||
|
|||||||
+43
-32
@@ -1,41 +1,52 @@
|
|||||||
# Architecture
|
# Native client architecture
|
||||||
|
|
||||||
Two independent native applications share a policy, not a cross-platform runtime:
|
The requested product is a native reconstruction of Yuvomi's PWA, not a native
|
||||||
|
window around that website. Both shipping entry points now render native views:
|
||||||
|
|
||||||
| Responsibility | Android | iOS |
|
| Responsibility | Android | iOS |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Native entry/configuration | ComponentActivity and platform widgets | SwiftUI |
|
| Screens and navigation | Jetpack Compose / Material 3 primitives, Yuvomi tokens | SwiftUI, Yuvomi tokens |
|
||||||
| Web application | Android WebView | WKWebView |
|
| Application state | AndroidViewModel + Compose state | MainActor ObservableObject |
|
||||||
| Server URL policy | ServerAddress | ServerAddress |
|
| JSON API | HttpsURLConnection, serialized worker | URLSession actor, bounded streaming delegate |
|
||||||
| Reachability/metadata | HttpsURLConnection, no redirects/cookies | Ephemeral URLSession, no redirects/cookies |
|
| Session ownership | Explicit origin-bound secure-cookie jar | Private ephemeral URLSession cookie storage |
|
||||||
| Authentication | Upstream web UI and OS cookie jar | Upstream web UI and WKWebsiteDataStore |
|
| Persistent cookies | AES-GCM, AndroidKeyStore key, origin as authenticated data | Keychain, WhenUnlockedThisDeviceOnly, origin-scoped account |
|
||||||
| OIDC | Separate restricted web view after consent | Separate restricted web view after consent |
|
| Server logic | Existing unmodified Yuvomi API | Existing unmodified Yuvomi API |
|
||||||
| Downloads | Origin-bound streaming / bounded blob capture and pull | WKDownload to temporary protected file, system export |
|
|
||||||
|
|
||||||
The client never reimplements a Yuvomi module or introduces a backend. The user
|
There is no WebView/WKWebView in either shipped source tree and no browser
|
||||||
selects the origin. Bootstrap calls check the actual upstream unauthenticated
|
fallback for missing modules. The old implementation and browser tests are
|
||||||
metadata contract before loading the server application. Configuration stores only
|
archived in `legacy/`; their results are historical, not evidence for this client.
|
||||||
the origin and a query/fragment-free last path; auth/reset/invite routes are not
|
|
||||||
restored. No native password or API-token storage exists.
|
|
||||||
|
|
||||||
The current web view remains alive across background/resume and ordinary rotation.
|
The first native slice contains HTTPS onboarding, setup/password/TOTP login,
|
||||||
Android handles orientation changes in the existing activity; process recreation
|
session restoration, a basic dashboard, task/note/shopping interactions, read-only
|
||||||
loads the remembered path and retains OS cookies, not unsaved web form memory.
|
permission handling and local sign-out/server removal. Exact feature and visual
|
||||||
iOS retains a StateObject-owned view; cold launch restores path and persistent
|
parity is tracked in [native parity](native-parity.md), not inferred from a list of
|
||||||
cookies. No resume reload is imposed. Native recovery offers Retry, Keep viewing,
|
navigation destinations. The other modules remain unfinished.
|
||||||
and server management without hiding the route back to configuration.
|
|
||||||
|
|
||||||
Server erasure destroys the browsing context and clears all website storage before
|
## Transport and state boundaries
|
||||||
another server is loaded. The local wipe does not invalidate the remote session;
|
|
||||||
logout is still a server-side operation. Web application history remains native
|
|
||||||
web history. External schemes, universal links and app links are not registered
|
|
||||||
because arbitrary self-hosted domains cannot be verified by this app in advance.
|
|
||||||
|
|
||||||
The optional integration build has a different Android package ID and adds trust
|
- One configured root HTTPS origin/port; system certificate validation only.
|
||||||
for a fresh test CA generated outside the repository. It uses the same production
|
- API calls never follow redirects. No cookie or Authorization state is replayed
|
||||||
code and the unmodified pinned upstream server. Neither normal debug nor release
|
to another host. Authentication proxies returning HTML are not treated as APIs.
|
||||||
resources include that CA. Never distribute an integration APK.
|
- JSON reads have byte limits and timeouts. Writes are not queued for offline
|
||||||
|
replay. Only a server-declared `csrf_invalid` rejection permits one token refresh
|
||||||
|
and retry; ordinary authorization failures and transport failures do not.
|
||||||
|
- Server session cookies are persisted, not passwords or TOTP/recovery codes.
|
||||||
|
Session-only cookies are not converted to long-lived cookies.
|
||||||
|
- Native UI mutations wait for the server result. Permissions remain enforced
|
||||||
|
server-side; sparse module/widget permissions also control native affordances.
|
||||||
|
- Local removal clears the native cookie vault and in-memory records. It is not
|
||||||
|
remote revocation. Logout attempts server revocation and still erases the local
|
||||||
|
session if the server cannot be reached.
|
||||||
|
- A prior WebView prototype installation may retain its old OS website data.
|
||||||
|
This data is never imported by the native client. Clear app data/reinstall the
|
||||||
|
prototype before reviewing this native preview if complete legacy erasure is
|
||||||
|
required; no migration of private household records is performed.
|
||||||
|
|
||||||
Read-only offline functionality belongs to upstream's service worker. The app
|
## Explicit gaps
|
||||||
preserves it where the platform engine supports it, but does not promise offline
|
|
||||||
editing, synchronization, or the same PWA cache behavior on all OS versions.
|
No native OIDC handoff has been implemented. A browser sign-in is not represented
|
||||||
|
as a successful native API session. Password reset/invitation flows, the remaining
|
||||||
|
modules, configurable dashboard, uploads/downloads, notification integrations,
|
||||||
|
offline cache, localization parity and visual baseline comparison remain open.
|
||||||
|
The signing setup was paused by the maintainer's native-rebuild correction; it
|
||||||
|
must not be used to label this incomplete client as a finished release.
|
||||||
+21
-3
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
Requirements: JDK 17, Android SDK platform 37.0, build-tools 36.0.0, current
|
Requirements: JDK 17, Android SDK platform 37.0, build-tools 36.0.0, current
|
||||||
platform-tools, and accepted Android SDK licenses. Minimum Android 8 (API 26).
|
platform-tools, and accepted Android SDK licenses. Minimum Android 8 (API 26).
|
||||||
Use a maintained Android System WebView. Target API 37. On Android 17, choose
|
The application surface is Jetpack Compose, not Android System WebView. Target
|
||||||
"Allow private-network servers" when using a LAN instance; public HTTPS servers
|
API 37. On Android 17, choose "Zugriff auf private Netzwerke erlauben" for a LAN instance; public HTTPS servers
|
||||||
do not need this optional runtime permission. No discovery/scanning is performed.
|
do not need this optional runtime permission. No discovery/scanning is performed.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -13,7 +13,7 @@ bash android/gradlew -p android connectedDebugAndroidTest
|
|||||||
```
|
```
|
||||||
|
|
||||||
Gradle 9.6.0 is checksum-verified by the wrapper. AGP 9.4.1 uses built-in Kotlin
|
Gradle 9.6.0 is checksum-verified by the wrapper. AGP 9.4.1 uses built-in Kotlin
|
||||||
with the build-cache fix in KGP 2.4.21. Maven versions are locked. No dynamic
|
with KGP and Compose compiler plugin 2.4.21. Maven versions are locked. No dynamic
|
||||||
application dependencies or private Maven repository is required.
|
application dependencies or private Maven repository is required.
|
||||||
|
|
||||||
Ordinary outputs:
|
Ordinary outputs:
|
||||||
@@ -23,6 +23,14 @@ Ordinary outputs:
|
|||||||
- `android/app/build/outputs/bundle/release/app-release.aab` (unsigned unless signed later)
|
- `android/app/build/outputs/bundle/release/app-release.aab` (unsigned unless signed later)
|
||||||
- `android/app/build/reports/` (lint, JVM and emulator results)
|
- `android/app/build/reports/` (lint, JVM and emulator results)
|
||||||
|
|
||||||
|
The Gitea build job uploads `android-native-debug-apk`, containing an installable
|
||||||
|
development-signed `app-debug.apk`. It is a native preview, not a signed stable
|
||||||
|
release or a claim of full PWA parity. See `native-parity.md` before testing it.
|
||||||
|
|
||||||
|
Native UI tests live in `src/androidTestNative/java` and the real-server native
|
||||||
|
scenario in `src/androidTestNativeIntegration/java`. The old browser tests and
|
||||||
|
renderer are archived under `legacy/` and are not compiled into the app/suites.
|
||||||
|
|
||||||
Immediately after building, collect and inspect the outputs:
|
Immediately after building, collect and inspect the outputs:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -60,6 +68,16 @@ Requires Node 22.14+ and a running emulator. The harness creates and removes its
|
|||||||
own CA/key/database, uses `adb reverse`, and builds `.integration` with explicit
|
own CA/key/database, uses `adb reverse`, and builds `.integration` with explicit
|
||||||
test trust. It does not weaken production TLS. Test credentials are ephemeral.
|
test trust. It does not weaken production TLS. Test credentials are ephemeral.
|
||||||
Keep test reports private if you customize the harness with real data (not advised).
|
Keep test reports private if you customize the harness with real data (not advised).
|
||||||
|
The native test calls the real API through native controls and saves a synthetic
|
||||||
|
dashboard screenshot under `app/build/outputs/native-screenshots/`. It does not
|
||||||
|
demonstrate native SSO merely because the protocol fixture also tests OIDC.
|
||||||
|
The test writes through `PlatformTestStorageRegistry`; AGP collects the file in
|
||||||
|
`outputs/connected_android_test_additional_output/integrationAndroidTest/` before
|
||||||
|
uninstalling the fixture. The harness rejects missing/ambiguous output and removes
|
||||||
|
only its known screenshot from previous runs. Do not extract app-private files
|
||||||
|
after Gradle returns: UTP has already uninstalled the `.integration` package.
|
||||||
|
Capture uses the native window and asserts nonuniform pixels; a valid PNG header
|
||||||
|
alone is not sufficient screenshot evidence.
|
||||||
|
|
||||||
For dependency updates run `:app:dependencies --write-locks`, the full pipeline,
|
For dependency updates run `:app:dependencies --write-locks`, the full pipeline,
|
||||||
and `python3 scripts/check-dependencies.py`. Review lockfile changes. The version
|
and `python3 scripts/check-dependencies.py`. Review lockfile changes. The version
|
||||||
|
|||||||
+8
-4
@@ -1,8 +1,8 @@
|
|||||||
# iOS development
|
# iOS development
|
||||||
|
|
||||||
Requires macOS, Xcode 16.4 or newer with an iOS simulator, and XcodeGen 2.44.1.
|
Requires macOS, Xcode 16.4 or newer with an iOS simulator, and XcodeGen 2.44.1.
|
||||||
Minimum iOS/iPadOS 18.4: the auth window must be able to deny native file-panel
|
Minimum iOS/iPadOS 18.4 is retained for this rebuild. The application surface is
|
||||||
requests, which earlier WKWebView delegates cannot do. No CocoaPods or external
|
SwiftUI; the old WKWebView renderer is archived, not shipped. No CocoaPods or external
|
||||||
runtime package is required. For App Store submission use Apple's currently
|
runtime package is required. For App Store submission use Apple's currently
|
||||||
required Xcode/iOS SDK, not merely the oldest compiler that can build the source.
|
required Xcode/iOS SDK, not merely the oldest compiler that can build the source.
|
||||||
|
|
||||||
@@ -29,11 +29,15 @@ swift test --package-path ios
|
|||||||
swiftc -frontend -parse ios/Sources/*.swift ios/Tests/*.swift ios/UITests/*.swift
|
swiftc -frontend -parse ios/Sources/*.swift ios/Tests/*.swift ios/UITests/*.swift
|
||||||
```
|
```
|
||||||
|
|
||||||
These portable tests compile the **production URL/metadata policies only**.
|
These portable tests compile the **production Foundation API transport, contracts
|
||||||
Parsing does not typecheck UIKit, SwiftUI or WebKit APIs. Neither command is
|
and URL/metadata policies**. Parsing does not typecheck SwiftUI or Security APIs. Neither command is
|
||||||
evidence that the iOS application builds. Actual Xcode testing is mandatory.
|
evidence that the iOS application builds. Actual Xcode testing is mandatory.
|
||||||
|
|
||||||
For a device build select your authorized development team in Xcode, use your own
|
For a device build select your authorized development team in Xcode, use your own
|
||||||
registered bundle identifier, and let Xcode manage development provisioning.
|
registered bundle identifier, and let Xcode manage development provisioning.
|
||||||
Never commit generated profiles or certificates. See `release-process.md` for
|
Never commit generated profiles or certificates. See `release-process.md` for
|
||||||
distribution. A Linux environment cannot produce a validated iOS archive.
|
distribution. A Linux environment cannot produce a validated iOS archive.
|
||||||
|
|
||||||
|
The Mac runner now bootstraps checksum-pinned native Node 22 before checkout,
|
||||||
|
because its JavaScript actions cannot start without Node in the service PATH.
|
||||||
|
This does not install/choose Xcode, accept its license or create a simulator.
|
||||||
@@ -42,6 +42,12 @@ Xcode 16.4+ (or a current release supporting this project), accept its license a
|
|||||||
complete first-launch setup. Install an iOS 18.4+ simulator runtime and create an
|
complete first-launch setup. Install an iOS 18.4+ simulator runtime and create an
|
||||||
available iPhone simulator; `select-simulator.py` chooses the newest eligible one.
|
available iPhone simulator; `select-simulator.py` chooses the newest eligible one.
|
||||||
|
|
||||||
|
Before the first JavaScript action, an inline shell bootstrap installs verified
|
||||||
|
native Node 22.22.1 into a versioned runner tool cache and exports its bin directory
|
||||||
|
through `GITHUB_PATH`. It needs no Homebrew/root access and remains available to
|
||||||
|
action post-cleanup. This addresses run #4's `Cannot find: node in PATH` failure;
|
||||||
|
the modified workflow itself still needs a real Mac run.
|
||||||
|
|
||||||
XcodeGen's pinned, checksum-verified binary includes native arm64 and x86_64
|
XcodeGen's pinned, checksum-verified binary includes native arm64 and x86_64
|
||||||
slices; Rosetta/Homebrew installation is not required by the workflow. Build,
|
slices; Rosetta/Homebrew installation is not required by the workflow. Build,
|
||||||
archive and Swift package scratch outputs use `RUNNER_TEMP`. Scratch directories
|
archive and Swift package scratch outputs use `RUNNER_TEMP`. Scratch directories
|
||||||
|
|||||||
+52
-1
@@ -1,4 +1,55 @@
|
|||||||
# Maintainer continuation
|
# Native rebuild continuation
|
||||||
|
|
||||||
|
## Current objective — do not restore the wrapper
|
||||||
|
|
||||||
|
The maintainer rejected the browser-wrapper architecture and requested the PWA's
|
||||||
|
appearance/functions implemented as genuine native screens. Shipping Android now
|
||||||
|
uses Compose and iOS SwiftUI, calling the existing API directly. `legacy/` holds
|
||||||
|
the superseded renderers/tests for reference only. No WebView fallback, raw-JSON
|
||||||
|
module placeholder or old browser-test pass may be represented as native parity.
|
||||||
|
|
||||||
|
Read [native parity](native-parity.md), [architecture](architecture.md), and
|
||||||
|
[current validation](validation.md) first. Initial auth/dashboard/tasks/notes/
|
||||||
|
shopping slices exist, but **no module has accepted full visual/functional parity**.
|
||||||
|
The remaining pages/settings/auth/file/offline/notification work is explicit.
|
||||||
|
|
||||||
|
The owner-authorized signing key and four Gitea secrets were created before this
|
||||||
|
correction. Their private backup is `/home/neste/yuvomi-signing/initial-20261021`.
|
||||||
|
Do not print its contents. Uncommitted signing changes are preserved in Git stash
|
||||||
|
`wip: owner-authorized signing setup paused for true native rewrite`; do not apply
|
||||||
|
them blindly or resume signing/publishing the old wrapper.
|
||||||
|
|
||||||
|
Current local native outputs/logs:
|
||||||
|
|
||||||
|
- `/home/neste/yuvomi-native-build` (use `YUVOMI_BUILD_DIR` on WSL).
|
||||||
|
- `/home/neste/yuvomi-native-validation.log` and native integration logs.
|
||||||
|
- `/home/neste/yuvomi-native-swift` and `/home/neste/yuvomi-native-swift.log`.
|
||||||
|
- The existing persistent SDK, Swift, ktlint, actionlint and unmodified upstream
|
||||||
|
paths listed below remain usable. Set `ANDROID_SERIAL=emulator-5554`; do not
|
||||||
|
authorize or deploy to unrelated devices visible in `adb devices`.
|
||||||
|
|
||||||
|
Run native JVM/Compose UI tests, the real upstream fixture, portable Swift API/
|
||||||
|
contract tests, formatting, lint and OSV after changes. Apple UI/Security.framework
|
||||||
|
is not typechecked by Linux. Gitea's Mac job now bootstraps pinned Node before
|
||||||
|
checkout, but actual Xcode results still need inspection. Ubuntu emulator jobs
|
||||||
|
continue requiring accessible KVM; do not weaken or fake that evidence.
|
||||||
|
|
||||||
|
Latest local native evidence: 10 JVM tests, 6 API-35 Compose tests, 7 real-server
|
||||||
|
instrumentation tests (including those same 6), both lint variants and native
|
||||||
|
debug/unsigned release APK/AAB builds pass. Sixteen portable Swift tests and strict
|
||||||
|
format/parsing pass. Screenshot export now uses AndroidX test storage/AGP output
|
||||||
|
collection before uninstall; the PNG was opened and confirmed nonblank. Five new
|
||||||
|
output-regression tests guard missing, invalid, ambiguous and stale screenshots.
|
||||||
|
See `validation.md` for logs and limitations. No Apple SDK result is implied.
|
||||||
|
|
||||||
|
The next Mac/Ubuntu workflow execution still needs inspection after pushing.
|
||||||
|
Rebuild/collect from a clean checkout; do not present cached wrapper artifacts as
|
||||||
|
the native preview. Keep the signing stash parked.
|
||||||
|
|
||||||
|
Next work: stabilize/visually compare this slice, close auth/advanced CRUD gaps,
|
||||||
|
then implement the remaining real native modules against the parity inventory.
|
||||||
|
|
||||||
|
## Historical environment and original delivery context
|
||||||
|
|
||||||
This is a development delivery, not authorization to publish. Preserve the Git
|
This is a development delivery, not authorization to publish. Preserve the Git
|
||||||
history on `feat/yuvomi-mobile`; use Conventional Commits and normal pushes only.
|
history on `feat/yuvomi-mobile`; use Conventional Commits and normal pushes only.
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# Historical architecture — superseded WebView prototype
|
||||||
|
|
||||||
|
Two independent native applications share a policy, not a cross-platform runtime:
|
||||||
|
|
||||||
|
| Responsibility | Android | iOS |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Native entry/configuration | ComponentActivity and platform widgets | SwiftUI |
|
||||||
|
| Web application | Android WebView | WKWebView |
|
||||||
|
| Server URL policy | ServerAddress | ServerAddress |
|
||||||
|
| Reachability/metadata | HttpsURLConnection, no redirects/cookies | Ephemeral URLSession, no redirects/cookies |
|
||||||
|
| Authentication | Upstream web UI and OS cookie jar | Upstream web UI and WKWebsiteDataStore |
|
||||||
|
| OIDC | Separate restricted web view after consent | Separate restricted web view after consent |
|
||||||
|
| Downloads | Origin-bound streaming / bounded blob capture and pull | WKDownload to temporary protected file, system export |
|
||||||
|
|
||||||
|
The client never reimplements a Yuvomi module or introduces a backend. The user
|
||||||
|
selects the origin. Bootstrap calls check the actual upstream unauthenticated
|
||||||
|
metadata contract before loading the server application. Configuration stores only
|
||||||
|
the origin and a query/fragment-free last path; auth/reset/invite routes are not
|
||||||
|
restored. No native password or API-token storage exists.
|
||||||
|
|
||||||
|
The current web view remains alive across background/resume and ordinary rotation.
|
||||||
|
Android handles orientation changes in the existing activity; process recreation
|
||||||
|
loads the remembered path and retains OS cookies, not unsaved web form memory.
|
||||||
|
iOS retains a StateObject-owned view; cold launch restores path and persistent
|
||||||
|
cookies. No resume reload is imposed. Native recovery offers Retry, Keep viewing,
|
||||||
|
and server management without hiding the route back to configuration.
|
||||||
|
|
||||||
|
Server erasure destroys the browsing context and clears all website storage before
|
||||||
|
another server is loaded. The local wipe does not invalidate the remote session;
|
||||||
|
logout is still a server-side operation. Web application history remains native
|
||||||
|
web history. External schemes, universal links and app links are not registered
|
||||||
|
because arbitrary self-hosted domains cannot be verified by this app in advance.
|
||||||
|
|
||||||
|
The optional integration build has a different Android package ID and adds trust
|
||||||
|
for a fresh test CA generated outside the repository. It uses the same production
|
||||||
|
code and the unmodified pinned upstream server. Neither normal debug nor release
|
||||||
|
resources include that CA. Never distribute an integration APK.
|
||||||
|
|
||||||
|
Read-only offline functionality belongs to upstream's service worker. The app
|
||||||
|
preserves it where the platform engine supports it, but does not promise offline
|
||||||
|
editing, synchronization, or the same PWA cache behavior on all OS versions.
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Historical server compatibility — superseded WebView prototype
|
||||||
|
|
||||||
|
Source reference: upstream 2.78.0 revision
|
||||||
|
`10bfef7686ed7303b4c74c7fcc55a5eb16356c9d`. No general version range has been
|
||||||
|
certified. Anonymous bootstrap metadata deliberately omits the exact version;
|
||||||
|
native probing verifies shape, not an invented minimum-version comparison.
|
||||||
|
|
||||||
|
Use `https://family.example.com` or `https://family.example.com:8443`, backed by a
|
||||||
|
root-hosted Yuvomi installation and a valid system-trusted certificate. Operators
|
||||||
|
should set `SESSION_SECURE=true`, correct `BASE_URL`, and correct proxy trust.
|
||||||
|
Private servers are supported through reachable HTTPS/VPN, not TLS bypasses.
|
||||||
|
International hostnames should be entered in ASCII/punycode for both platforms.
|
||||||
|
|
||||||
|
Root-relative assets, API endpoints, cookie paths, callback redirects and worker
|
||||||
|
registration mean `/yuvomi/` subpaths are not supported by the inspected source.
|
||||||
|
Use a dedicated hostname. Reverse proxies must pass `/api/v1/*`, cookies, HTML,
|
||||||
|
JavaScript and the service worker consistently. An external authentication proxy
|
||||||
|
that intercepts bootstrap calls is rejected with a connection error; it is not
|
||||||
|
silently identified as a Yuvomi server.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
Password login, TOTP/recovery codes, password reset, invitations, server-side
|
||||||
|
session expiry/revocation and logout remain upstream web flows. No native code
|
||||||
|
stores the password, supplies a CSRF bypass, or extends an expired session.
|
||||||
|
Backgrounding does not clear cookies. Native server erasure does not revoke a
|
||||||
|
remote session; use Yuvomi logout first or revoke sessions server-side.
|
||||||
|
|
||||||
|
### OIDC: local fixture verified; real-provider validation pending
|
||||||
|
|
||||||
|
The initiating Yuvomi session contains OIDC state, nonce and PKCE verifier. When
|
||||||
|
the server redirects to an identity provider, native consent offers an isolated
|
||||||
|
web sign-in window sharing the OS website cookie store. HTTPS-only redirects
|
||||||
|
can return to the server callback; the final same-origin page returns to the main
|
||||||
|
view. No app-capability handlers or JS bridge are installed in that auth window.
|
||||||
|
|
||||||
|
Some providers (including configurations that prohibit embedded user agents)
|
||||||
|
require a system browser. **Those cannot sign the native view in with upstream's
|
||||||
|
current protocol.** Use Server settings -> Open server in browser, and sign in
|
||||||
|
there for an independent browser session. Opening only the external authorization
|
||||||
|
link in a browser does not transfer the initiating cookie. Browser cookies are
|
||||||
|
never copied into the app, and custom-scheme callbacks are not fabricated.
|
||||||
|
|
||||||
|
The API 35 integration suite completes a native isolated-window round trip with
|
||||||
|
a local test IdP, real RS256 ID tokens, nonce and S256 PKCE. No external
|
||||||
|
IdP/developer account was supplied. Validate the actual provider, including
|
||||||
|
cross-site cookies, cancellation, errors, TOTP and account linking, before relying
|
||||||
|
on that deployment. iOS authentication has not run against Apple SDKs. A native
|
||||||
|
browser handoff would require an independently reviewed upstream protocol; no
|
||||||
|
such upstream change is included or published.
|
||||||
|
|
||||||
|
Android generated exports require a current WebView supporting document-start
|
||||||
|
scripts and are capped at 25 MB. A bounded Blob registry preserves a generated
|
||||||
|
file even when upstream immediately revokes its object URL; it does not fetch
|
||||||
|
blob URLs or alter the server's CSP. HTTPS file downloads are capped at 100 MB.
|
||||||
|
Update the system WebView if generated exports are unavailable on an old engine.
|
||||||
|
|
||||||
|
## Notifications and offline
|
||||||
|
|
||||||
|
Upstream implements Web Push and optional ntfy/Gotify/webhook/email channels.
|
||||||
|
Embedded web views do not supply a portable native push subscription. This app
|
||||||
|
has **no native remote-push claim**, no Firebase/APNs secrets, no background
|
||||||
|
polling service, and no fake notification-registration UI. Configure an existing
|
||||||
|
optional upstream ntfy/Gotify channel and its client if desired. No centralized
|
||||||
|
service is required by this application.
|
||||||
|
|
||||||
|
Upstream service-worker caching is read-only, allow-listed, and versioned.
|
||||||
|
Mutations/authentication remain online. Platform-specific cache/resume behavior
|
||||||
|
and offline account switching still need device validation. Do not rely on offline
|
||||||
|
editing, synchronization, or closed-app push in this native development build.
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Historical security review — superseded WebView prototype
|
||||||
|
|
||||||
|
This is an engineering review, not an independent penetration test or certification.
|
||||||
|
|
||||||
|
Addressed during implementation:
|
||||||
|
|
||||||
|
- Canonical, HTTPS-only origin/port comparison; credential, fragment, query,
|
||||||
|
subpath, scheme, lookalike-host and TLS-downgrade regression cases.
|
||||||
|
- A main-frame POST can bypass Android's usual navigation callback. The request
|
||||||
|
interception gate now rejects **all** cross-origin requests, not only subresources.
|
||||||
|
The emulator regression was observed failing when the main-frame guard was
|
||||||
|
deliberately removed, then rerun with the fix restored.
|
||||||
|
- TLS failures cancel by default. Native download redirects are refused before
|
||||||
|
cookies can be replayed to another origin. Bootstrap requests use neither
|
||||||
|
cookies nor automatic redirects and have bounded metadata reads/timeouts.
|
||||||
|
- Files use explicit system selection/content URIs; no filesystem or storage
|
||||||
|
permission is granted to web content. Blob exports have no native JS bridge.
|
||||||
|
- Complete Android browsing-data deletion uses WebStorageCompat, with OS app
|
||||||
|
reset for engines without that capability. WebStorage.deleteAllData alone was
|
||||||
|
insufficient for service-worker CacheStorage/IndexedDB and is not relied upon.
|
||||||
|
- iOS server erase replaces the WKWebView, not only its URL, eliminating old
|
||||||
|
history/back-forward contexts as well as persistent website data.
|
||||||
|
- iOS metadata uses typed decoding, rejecting numeric values masquerading as booleans.
|
||||||
|
- Native picker results are bound to the browsing generation/request. Android
|
||||||
|
rejects stale upload/download selections, revokes camera URI grants, and clears
|
||||||
|
capture cache on erasure. iOS ignores export-cancellation callbacks from an old
|
||||||
|
download. Apple-specific callback regressions have not run without Xcode.
|
||||||
|
- KGP was upgraded after OSV identified CVE-2026-53914 in the original build tool.
|
||||||
|
The final OSV scan found no listed advisories across 213 locked/direct Maven
|
||||||
|
coordinates and build plugins. Rescan after resolution/lock updates.
|
||||||
|
- The inspected release APK is not debuggable, rejects cleartext, disables backup
|
||||||
|
and trusts system CAs only. AndroidX's exported profile installer receiver is
|
||||||
|
protected by the system DUMP permission; app providers are not exported.
|
||||||
|
|
||||||
|
Release gates still requiring evidence:
|
||||||
|
|
||||||
|
- Actual Xcode typecheck, simulator, archive, physical-device and accessibility review.
|
||||||
|
- End-to-end IdP flows, especially providers that prohibit embedded agents; no
|
||||||
|
browser-to-native session transfer is supported by the current upstream protocol.
|
||||||
|
- iOS unknown-length download disk-pressure behavior; a post-download size check
|
||||||
|
is not a streaming quota. Verify file picker/camera cancellation on real devices.
|
||||||
|
- Android file-picker/camera/rotation while a picker is outstanding; cancellation
|
||||||
|
on process death intentionally loses the selection, never silently retries it.
|
||||||
|
- Offline sign-out/account switching, stale-worker updates and server erasure on
|
||||||
|
current WebView/WKWebView versions. Upstream tests are not native device proof.
|
||||||
|
- Reverify final signed release manifests, signing, store ownership, private vulnerability contact
|
||||||
|
and applicable privacy disclosures. No claim that all vulnerabilities are absent.
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
# Historical validation — superseded WebView prototype
|
||||||
|
|
||||||
|
These results describe the old wrapper, not the current native implementation.
|
||||||
|
See [current native validation](validation.md).
|
||||||
|
|
||||||
|
**Partially verified development software, not production-ready.**
|
||||||
|
Local validation date: 2026-10-21. No unexecuted iOS application test, hosted CI
|
||||||
|
run, production signing, or store publication is represented as completed.
|
||||||
|
|
||||||
|
## Executed evidence
|
||||||
|
|
||||||
|
- Android debug APK and unsigned release APK/AAB built successfully; both
|
||||||
|
`lintDebug` and `lintRelease` passed. JVM security/picker-policy tests: **7 passed,
|
||||||
|
zero failures/skips**.
|
||||||
|
- Android API 35 regular emulator suite: **6 passed, zero failures/skips**.
|
||||||
|
This covers onboarding, invalid URLs, background/resume, hardened settings,
|
||||||
|
cross-origin POST/subresource isolation, opaque-page Blob rejection and activity
|
||||||
|
recreation. Its permission test checks that the API 37 permission UI is absent;
|
||||||
|
it is **not** evidence of API 37 permission grant/denial behavior.
|
||||||
|
- Unmodified pinned upstream ran behind a temporary HTTPS reverse proxy.
|
||||||
|
Bootstrap metadata, password login, Secure/HttpOnly/SameSite cookies, persistent
|
||||||
|
session, CSRF rejection, logout/revocation passed in the harness.
|
||||||
|
- Android's extended real-server scenario exercises login, HttpOnly cookies,
|
||||||
|
document upload via upstream fetch, native FileTransfer output, bounded Blob
|
||||||
|
export, background/resume, recreation, CSRF-protected logout, revocation,
|
||||||
|
recovery, isolated OIDC return and back navigation. It does not automate the OS
|
||||||
|
camera/document destination picker or prove every upstream module works.
|
||||||
|
Two consecutive API 35 runs have **7 passed, zero failures/skips each**, including the
|
||||||
|
six regular security/onboarding cases and this real-server scenario.
|
||||||
|
- The cross-origin POST regression was deliberately observed failing without its
|
||||||
|
guard. The production guard was restored and the API 35 regression passes.
|
||||||
|
- Portable Swift production-policy tests: 7 passed (URL and typed metadata).
|
||||||
|
All Swift sources passed format lint and parsing with Swift 6.2.1 on Linux.
|
||||||
|
The portable package excludes BrowserModelTests. This does not build iOS.
|
||||||
|
- Selected upstream suites ran successfully: cookie-secure-flag (4),
|
||||||
|
session-sliding (8), two-factor (22), password-reset (24), sw-api-cache (42).
|
||||||
|
Upstream's plain OIDC script also exited successfully. These are upstream tests,
|
||||||
|
not evidence of a provider round-trip or native push support.
|
||||||
|
- The HTTPS harness independently passed upstream OIDC discovery, RS256 ID-token
|
||||||
|
signature/nonce validation, S256 PKCE exchange and session creation with a local
|
||||||
|
test IdP. The fixture checks single-use codes, exact redirect URIs and OAuth
|
||||||
|
Basic client authentication. Loopback hosts/ports and automatic fixture consent
|
||||||
|
are not representative of every provider's cross-site/embedded-agent policies.
|
||||||
|
- OSV: no listed advisories for **213** locked/direct Maven coordinates and build
|
||||||
|
plugins at scan time. This is not a guarantee that no vulnerabilities exist.
|
||||||
|
- ktlint 1.7.1, actionlint 1.7.7, repository invariants, Python compilation,
|
||||||
|
Node syntax and shell syntax checks passed. JUnit-verifier regression suite:
|
||||||
|
**8 passed**, including rejection of absent, empty, malformed, insufficient,
|
||||||
|
failed, errored and skipped evidence.
|
||||||
|
- Release APK inspection confirms API 26 minimum / API 37 target, no debuggable
|
||||||
|
flag, backups and cleartext disabled, system-only certificate trust. Exported
|
||||||
|
entry points are the launcher and AndroidX ProfileInstallReceiver protected by
|
||||||
|
the system DUMP permission; file/startup providers are not exported. Debug APK
|
||||||
|
signature verifies; release APK/AAB are unsigned. Collected archives contain no
|
||||||
|
fixture CA/key or signing-key files.
|
||||||
|
|
||||||
|
## Emulator limitations and retry evidence
|
||||||
|
|
||||||
|
Earlier extended-suite attempts crashed the host emulator with SIGSEGV under
|
||||||
|
software/off GPU modes. Host-GPU mode remained running and produced actionable
|
||||||
|
JUnit failures: an OIDC-return synchronization timeout, followed by an outage
|
||||||
|
assertion that incorrectly assumed the upstream worker could not serve its cached
|
||||||
|
app shell, then a document-readiness race after recreation. Tests now verify the
|
||||||
|
loaded JavaScript origin, wait for the sign-in window to close, retry only a probe
|
||||||
|
lost to document replacement and exercise recovery through uncached metadata.
|
||||||
|
The completed retry passes all seven tests without disabling the worker or
|
||||||
|
weakening production TLS/CSP/origin policies.
|
||||||
|
|
||||||
|
API 37 attempts encountered broken package/activity services and locked
|
||||||
|
credential-encrypted storage. **No API 37 runtime pass is claimed.**
|
||||||
|
|
||||||
|
Local logs and reports live in `/home/neste/yuvomi-build/`; test XML is under
|
||||||
|
`app/outputs/androidTest-results/connected/`. Earlier failing JUnit snapshots are
|
||||||
|
preserved as `integration-host-gpu-oidc-race.xml` and
|
||||||
|
`integration-host-gpu-sw-cache.xml`, plus
|
||||||
|
`integration-host-gpu-document-ready.xml`. Passing evidence is preserved in
|
||||||
|
`integration-api35-first-pass.xml` and `integration-api35-repeat-pass.xml`; logs are
|
||||||
|
`upstream-integration-final-retry.log` and `upstream-integration-repeat.log`.
|
||||||
|
These files are local evidence, not published
|
||||||
|
artifacts or a hosted CI result.
|
||||||
|
|
||||||
|
Test environment: JDK 17.0.20.1, Node 22.22.1, Python 3.14.4, Android Emulator
|
||||||
|
37.2.12, API 35 x86_64 Google APIs image, WebView 124.0.6367.219. The old bundled
|
||||||
|
WebView is useful compatibility evidence, not a recommendation to use an unpatched
|
||||||
|
engine; a current engine/device run remains mandatory.
|
||||||
|
|
||||||
|
## Artifacts
|
||||||
|
|
||||||
|
Ignored `artifacts/android/` contains the development-signed debug APK and unsigned
|
||||||
|
release APK/AAB, `SHA256SUMS`, `build-info.json` and manifest/policy/signature
|
||||||
|
inspection evidence. No integration APK is collected. No IPA or Apple archive
|
||||||
|
exists. See [Android build](build-android.md) for repeatable collection commands.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bash android/gradlew -p android testDebugUnitTest lintDebug lintRelease assembleDebug assembleRelease bundleRelease connectedDebugAndroidTest
|
||||||
|
python3 scripts/test-integration.py /path/to/pinned-upstream --android
|
||||||
|
swift test --package-path ios
|
||||||
|
swiftc -frontend -parse ios/Sources/*.swift ios/Tests/*.swift ios/UITests/*.swift
|
||||||
|
python3 scripts/check-repository.py
|
||||||
|
python3 scripts/check-dependencies.py
|
||||||
|
python3 scripts/test-verifier.py
|
||||||
|
python3 scripts/collect-android-artifacts.py
|
||||||
|
git diff --check
|
||||||
|
```
|
||||||
|
|
||||||
|
This environment is Linux/WSL. Android SDK and a KVM emulator were installed for
|
||||||
|
real execution. Build output relocation was needed because the Windows mount
|
||||||
|
rejects some Gradle POSIX metadata operations. Swift's Linux toolchain was
|
||||||
|
installed for portable tests. No macOS, Xcode, Apple simulator or physical device
|
||||||
|
is available; no iOS build/archive/UI result is claimed.
|
||||||
|
|
||||||
|
## Mandatory remaining evidence
|
||||||
|
|
||||||
|
- Run Xcode build, XCTest/UI tests and unsigned archive on macOS; fix any compiler
|
||||||
|
or runtime issues. The app has **not** yet been typechecked against Apple SDKs.
|
||||||
|
- Validate real IdPs: cancellation, account linking, TOTP after OIDC, and embedded
|
||||||
|
provider policy. Browser-only providers have no native-session handoff upstream.
|
||||||
|
- Real-device camera/document picker cancellation, file MIME cases, rotation with
|
||||||
|
an outstanding picker, network loss/reconnect, process kill/memory pressure,
|
||||||
|
session expiry/revocation, OS backup, and offline account isolation.
|
||||||
|
- Android 17 private-network permission grant/denial/revocation on a matching OS.
|
||||||
|
Also run minimum-supported API 26 and a current OS/WebView device matrix.
|
||||||
|
- VoiceOver/TalkBack, large text, contrast, keyboard/safe areas, reduced motion,
|
||||||
|
light/dark appearance and responsive web modules on actual supported devices.
|
||||||
|
- Successful CI runs on the configured Gitea runners, private security
|
||||||
|
reporting contact, human security review, store ownership and production signing.
|
||||||
|
|
||||||
|
No Firebase/APNs registration, closed-app push, offline editing, App Store approval,
|
||||||
|
signing, publication or physical-device validation is claimed. See `SECURITY.md`
|
||||||
|
and `docs/security-review.md` for residual limitations.
|
||||||
|
Resume work using [maintainer continuation](continuation.md).
|
||||||
|
|
||||||
|
## Gitea runner adaptation
|
||||||
|
|
||||||
|
Workflows now live in `.gitea/workflows/` and target the supplied `ubuntu-latest`
|
||||||
|
pool and native `macos-arm64` M4 Pro runner. Local workflow grammar lint (Gitea URL
|
||||||
|
syntax normalized), repository invariants, shell/Python syntax, ten mocked runner
|
||||||
|
preflight regressions and eight evidence-verifier regressions pass. SHA-256 Git
|
||||||
|
initialization/fetch was exercised locally; the pinned XcodeGen archive's checksum
|
||||||
|
and native arm64 slice were verified. These are not remote runner execution or
|
||||||
|
Apple SDK results. See [runner requirements](ci-runners.md); the local emulator
|
||||||
|
preflight currently rejects unavailable/inaccessible KVM as designed. Original
|
||||||
|
application build evidence above remains historical and is not a rebuild of the
|
||||||
|
workflow-only changes.
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
# YUVOMI MOBILE – FINAL DELIVERY REPORT
|
||||||
|
|
||||||
|
**Delivery status: incomplete native preview, not final product acceptance.**
|
||||||
|
This report closes the initial native rebuild slice, not the requested complete
|
||||||
|
1:1 replacement. No module has accepted functional and visual parity.
|
||||||
|
|
||||||
|
## 1. Outcome
|
||||||
|
|
||||||
|
The rejected embedded-browser application has been replaced by genuine native
|
||||||
|
shipping entry points. Missing modules do not fall back to a WebView.
|
||||||
|
|
||||||
|
## 2. Upstream reference
|
||||||
|
|
||||||
|
Unmodified Yuvomi 2.78.0, commit
|
||||||
|
`10bfef7686ed7303b4c74c7fcc55a5eb16356c9d`. No upstream change or push.
|
||||||
|
|
||||||
|
## 3. Android
|
||||||
|
|
||||||
|
Kotlin/Compose onboarding, setup/password/TOTP interfaces, basic dashboard,
|
||||||
|
tasks/notes/shopping and session management. Version `0.2.0-native-preview`,
|
||||||
|
code 2. This is a tested initial slice, not full module coverage.
|
||||||
|
|
||||||
|
## 4. iOS
|
||||||
|
|
||||||
|
SwiftUI equivalents, native API models/transport and Keychain storage implemented.
|
||||||
|
Sixteen portable tests pass; Apple SDK application/UI/Keychain validation remains
|
||||||
|
unverified locally. No installable IPA or App Store-ready archive is claimed.
|
||||||
|
|
||||||
|
## 5. Design parity
|
||||||
|
|
||||||
|
Upstream colors, spacing/radii and brand geometry guide native controls. One real
|
||||||
|
synthetic Android dashboard screenshot was inspected. No side-by-side full PWA
|
||||||
|
visual acceptance, complete adaptive-layout or accessibility approval yet.
|
||||||
|
|
||||||
|
## 6. API and architecture
|
||||||
|
|
||||||
|
Direct same-origin HTTPS/JSON, native controls and state; server-owned business
|
||||||
|
logic and authorization. Superseded browser code/tests are preserved in `legacy/`
|
||||||
|
but excluded from shipping builds and native test counts.
|
||||||
|
|
||||||
|
## 7. Security
|
||||||
|
|
||||||
|
System TLS, redirect refusal, bounded reads, upstream CSRF and protected native
|
||||||
|
cookies. AndroidKeyStore/AES-GCM and iOS Keychain/private URLSession storage; no
|
||||||
|
stored passwords, test CA in ordinary builds or hidden browser session import.
|
||||||
|
Human security review and additional device/role/error-path coverage remain open.
|
||||||
|
|
||||||
|
## 8. Executed validation
|
||||||
|
|
||||||
|
10 JVM tests, 6 native API-35 UI tests, the 7-test real-server suite (including
|
||||||
|
those same 6), both Android lint variants and package builds pass. Swift has 16
|
||||||
|
portable passes plus strict formatting/parsing. 23 script regressions, repository
|
||||||
|
checks, workflow lint and the 266-coordinate OSV scan pass. See
|
||||||
|
[validation](validation.md) for evidence, failures corrected and exact limitations.
|
||||||
|
|
||||||
|
## 9. Artifacts
|
||||||
|
|
||||||
|
The local collector replaces old wrapper outputs in ignored `artifacts/android/`
|
||||||
|
with native debug APK and unsigned release APK/AAB, checksums and manifest/network/
|
||||||
|
signature inspection. `build-info.json` records exact source identity and dirty
|
||||||
|
state. Only the development-signed debug APK is installable as provided.
|
||||||
|
|
||||||
|
## 10. Gitea CI
|
||||||
|
|
||||||
|
The Android workflow offers `android-native-debug-apk`; the Mac workflow bootstraps
|
||||||
|
verified ARM64 Node before checkout. Actual artifact publication and Apple build
|
||||||
|
results require remote-run inspection. Remote Ubuntu emulator jobs need KVM access;
|
||||||
|
local emulator success is not a substitute for a passing remote matrix.
|
||||||
|
|
||||||
|
## 11. Signing and publication
|
||||||
|
|
||||||
|
Initial owner-authorized signing material/secrets are preserved privately; signing
|
||||||
|
workflow changes remain parked in the named stash. No production-signed native
|
||||||
|
release, store submission or claim of completed product delivery.
|
||||||
|
|
||||||
|
## 12. Remaining work
|
||||||
|
|
||||||
|
Native SSO/recovery/invitations, advanced first-slice controls, the remaining
|
||||||
|
modules/settings, files, offline, notifications, Apple/device validation and 1:1
|
||||||
|
visual/behavior acceptance remain substantial work. The complete page inventory
|
||||||
|
and acceptance criteria are in [native parity](native-parity.md).
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# Native parity tracker
|
||||||
|
|
||||||
|
## Acceptance contract
|
||||||
|
|
||||||
|
**Native means native screens, forms, lists, navigation and interaction.** Android
|
||||||
|
uses Kotlin/Compose; iOS uses SwiftUI. PWA HTML/JavaScript is not embedded as the
|
||||||
|
application surface. The PWA is the design/behavior reference, not the renderer.
|
||||||
|
|
||||||
|
Reference: unmodified upstream 2.78.0,
|
||||||
|
`10bfef7686ed7303b4c74c7fcc55a5eb16356c9d`. The scope includes its thirty page
|
||||||
|
modules, settings leaves, permissions, dashboard customization and cross-module
|
||||||
|
workflows. Third-party web extensions need an explicit native integration design;
|
||||||
|
arbitrary server-installed HTML cannot silently become a native module.
|
||||||
|
|
||||||
|
Use these states honestly:
|
||||||
|
|
||||||
|
- **Slice**: real native UI/API interaction exists, with the listed limitations.
|
||||||
|
- **Pending**: not implemented. No fake screen, raw-JSON editor or WebView fallback.
|
||||||
|
- **Parity accepted**: requires functional and visual evidence on both platforms.
|
||||||
|
**No module currently has this status.**
|
||||||
|
|
||||||
|
## Page inventory
|
||||||
|
|
||||||
|
| Upstream page | Native status | Work still required before parity |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| login | Slice: password + TOTP/recovery step | OIDC/provider policy, recovery/error UX, localization, visual comparison |
|
||||||
|
| setup | Slice: initial household creation | Full onboarding and configuration workflow |
|
||||||
|
| forgot-password | Pending | Native recovery request and server-capability UX |
|
||||||
|
| reset-password | Pending | Native reset token/confirmation flow |
|
||||||
|
| join | Pending | Invitations, account setup, validation |
|
||||||
|
| dashboard | Slice: task/calendar/shopping/note previews | All remaining widgets, user layout/options, timezone-aware presentation, quick add, wall mode |
|
||||||
|
| tasks | Slice: list/search/status filter/create/edit/complete/delete | Category/assignee/tag/visibility controls, recurrence, subtasks, attachments, comments, archive/history, lock UX, bulk/sync controls |
|
||||||
|
| shopping | Slice: lists/items/create/edit/check/delete | List rename/duplicate, categories, ordering, suggestions, live versions, prices/stores, imports/send/undo |
|
||||||
|
| notes | Slice: list/search/create/edit/pin/delete | Markdown/checklists, categories, note colors, ordering and concurrent edit UX |
|
||||||
|
| calendar | Dashboard preview only; module pending | Agenda/week/month, editing, recurrence/scopes, source calendars, timezone behavior, attachments/sync |
|
||||||
|
| schedule | Pending | Shift grid, roster, creation and settings |
|
||||||
|
| birthdays | Pending | Date/age privacy, contacts, reminders/import |
|
||||||
|
| contacts | Pending | Address book, editing, links/import/export |
|
||||||
|
| documents | Pending | Browse/search, metadata, native upload/camera/export and lifecycle tests |
|
||||||
|
| inventory | Pending | Items, locations, guarantees, attachments and reminders |
|
||||||
|
| meals | Pending | Meal plan, ingredients, household options and shopping transfer |
|
||||||
|
| recipes | Pending | Search/detail/editor, source import, images, pantry/shopping cross-links |
|
||||||
|
| pantry | Pending | Stock, batches/expiry, locations, quantity controls and shopping transfer |
|
||||||
|
| budget | Pending | Accounts, entries, categories, currency/amount handling and attachments |
|
||||||
|
| budget-plans | Pending | Plan editor, period/category matching and forecasts |
|
||||||
|
| budget-stats | Pending | Native charts and filters matching upstream calculations |
|
||||||
|
| subscriptions | Pending | Lifecycle, billing, recurrence and linked budget behavior |
|
||||||
|
| split-expenses | Pending | Groups, guests, balances, settlement and permission distinctions |
|
||||||
|
| housekeeping | Pending | Visits, tasks, time and role-gated payment data |
|
||||||
|
| waste | Pending | Schedules, pickup display/import and reminders |
|
||||||
|
| rewards | Pending | Catalog, ledger, goals, approvals and pocket-money precision |
|
||||||
|
| health | Pending | Medication, cycle, nutrition and capability-gated private views |
|
||||||
|
| health-fasting | Pending | Clock, history, capabilities and lifecycle behavior |
|
||||||
|
| settings | Slice: native logout/server removal only | Every relevant personal/admin settings leaf and native permissions |
|
||||||
|
| pair-display | Pending | Pairing protocol, display role and shared-surface privacy |
|
||||||
|
|
||||||
|
## Design reference
|
||||||
|
|
||||||
|
Native primitives reuse the upstream warm palette (`#F5F3ED` / `#191816`), opaque
|
||||||
|
surfaces (`#FFFFFF` / `#2B2825`), violet accent, 16-point cards, 26-point auth panel,
|
||||||
|
pill navigation/buttons and the exact three-circle brand geometry. These are
|
||||||
|
initial design-token mappings, **not proof of 1:1 visuals**. Material/SF symbols,
|
||||||
|
typography, sheets, adaptive layouts and module details still need comparison.
|
||||||
|
|
||||||
|
Every accepted module needs side-by-side screenshots from matching server data,
|
||||||
|
light/dark and small/large text coverage, keyboard/safe-area/back behavior,
|
||||||
|
read-only/denied permission cases and real API success/error tests. Android's
|
||||||
|
integration test exports a synthetic-fixture native dashboard screenshot; it is
|
||||||
|
not a production screenshot or a visual-parity approval.
|
||||||
|
|
||||||
|
## Implementation order
|
||||||
|
|
||||||
|
1. Stabilize the current native authentication/dashboard/tasks/notes/shopping
|
||||||
|
slice, including Apple SDK compilation and actual native tests.
|
||||||
|
2. Close auth/recovery/SSO and first-slice feature gaps, then accept those screens
|
||||||
|
against PWA visual/behavior baselines rather than adding empty menu entries.
|
||||||
|
3. Implement calendar/family/contacts, kitchen/pantry, documents/inventory, then
|
||||||
|
finance, household, rewards and health as separately tested native slices.
|
||||||
|
4. Complete settings, extensions/cross-module flows, accessibility, offline and
|
||||||
|
notifications. Audit every upstream route/settings leaf before claiming parity.
|
||||||
|
|
||||||
|
## Signing work retained, not released
|
||||||
|
|
||||||
|
The owner-authorized initial signing key and four Gitea repository secrets were
|
||||||
|
created before the native correction. The private backup remains outside Git at
|
||||||
|
`/home/neste/yuvomi-signing/initial-20261021`. Never print/commit its contents.
|
||||||
|
The uncommitted signing-workflow changes were preserved in Git stash
|
||||||
|
`wip: owner-authorized signing setup paused for true native rewrite`; do not apply
|
||||||
|
it blindly to the new workflows. No signing-secret values belong in screenshots,
|
||||||
|
test fixtures, documentation, commits or artifacts. Native signing/release work
|
||||||
|
remains paused until this preview's scope is explicitly accepted.
|
||||||
@@ -10,14 +10,14 @@ to either store. A debug APK or unsigned archive is not a production release.
|
|||||||
a provisional community identifier, not proof of registry/store ownership.
|
a provisional community identifier, not proof of registry/store ownership.
|
||||||
Confirm use of the Yuvomi name, required attribution and independent status.
|
Confirm use of the Yuvomi name, required attribution and independent status.
|
||||||
3. Bump version/name/code in Android and the iOS project spec; update CHANGELOG.
|
3. Bump version/name/code in Android and the iOS project spec; update CHANGELOG.
|
||||||
4. Run JVM/emulator/real-upstream HTTPS tests, portable Swift and Xcode simulator
|
4. Run native JVM/Compose/emulator/real-upstream HTTPS tests, portable Swift and Xcode simulator
|
||||||
tests, static checks, OSV scan, release builds and artifact inspection. Record
|
tests, static checks, OSV scan, release builds and artifact inspection. Record
|
||||||
upstream revision, app SHA, OS/WebView/Xcode versions, results and checksums.
|
upstream revision, app SHA, OS/SDK/Xcode versions, results and checksums.
|
||||||
5. Produce signed artifacts only using an authorized maintainer's credentials.
|
5. Produce signed artifacts only using an authorized maintainer's credentials.
|
||||||
6. Review store privacy/Data Safety answers for the app AND selected-server model,
|
6. Review store privacy/Data Safety answers for the app AND selected-server model,
|
||||||
permission rationale, encryption/export compliance, screenshots, support URL,
|
permission rationale, encryption/export compliance, screenshots, support URL,
|
||||||
vulnerability contact, and device demonstrations. A functional web companion
|
vulnerability contact, and device demonstrations. An incomplete native preview
|
||||||
is not guaranteed to pass Apple's minimum-functionality review.
|
is not a finished PWA replacement or App Store approval.
|
||||||
7. Create a release/tag and publish artifacts/store submissions manually only
|
7. Create a release/tag and publish artifacts/store submissions manually only
|
||||||
after explicit maintainer authorization. Never force-push or rewrite history.
|
after explicit maintainer authorization. Never force-push or rewrite history.
|
||||||
|
|
||||||
@@ -31,7 +31,10 @@ An authorized maintainer must separately sign the verified APK/AAB using their
|
|||||||
own keystore, alias and passwords with `zipalign`, `apksigner`, and `jarsigner`.
|
own keystore, alias and passwords with `zipalign`, `apksigner`, and `jarsigner`.
|
||||||
Keep private material in a protected signing environment, never on the general
|
Keep private material in a protected signing environment, never on the general
|
||||||
validation runners. Securely back up the real upload key and use Play App Signing
|
validation runners. Securely back up the real upload key and use Play App Signing
|
||||||
according to the owner's policy. No production key is generated here.
|
according to the owner's policy. An initial owner-authorized key and repository
|
||||||
|
secrets already exist outside Git; signing workflow changes are parked during
|
||||||
|
the native rebuild. Preserve the key, do not generate a replacement or apply the
|
||||||
|
old signing stash without review. See `native-parity.md`.
|
||||||
Manually verify APK/AAB signatures and inspect
|
Manually verify APK/AAB signatures and inspect
|
||||||
the final manifest: no debuggable flag, HTTP/test CA or unintended exported component.
|
the final manifest: no debuggable flag, HTTP/test CA or unintended exported component.
|
||||||
Never distribute an `.integration` package or include its generated test resources.
|
Never distribute an `.integration` package or include its generated test resources.
|
||||||
|
|||||||
+31
-42
@@ -1,47 +1,36 @@
|
|||||||
# Security review record
|
# Native security review record
|
||||||
|
|
||||||
This is an engineering review, not an independent penetration test or certification.
|
This is an engineering checklist, not an independent audit or release approval.
|
||||||
|
The wrapper review is retained separately as
|
||||||
|
[historical evidence](legacy-wrapper-security-review.md).
|
||||||
|
|
||||||
Addressed during implementation:
|
## Implemented controls to exercise
|
||||||
|
|
||||||
- Canonical, HTTPS-only origin/port comparison; credential, fragment, query,
|
- Origin-bound HTTPS API transports, no redirects, no production test-CA bypass.
|
||||||
subpath, scheme, lookalike-host and TLS-downgrade regression cases.
|
- Server-owned session and CSRF semantics, no persistent password storage.
|
||||||
- A main-frame POST can bypass Android's usual navigation callback. The request
|
- Origin-bound AES-GCM/AndroidKeyStore cookies; iOS Keychain protected
|
||||||
interception gate now rejects **all** cross-origin requests, not only subresources.
|
WhenUnlockedThisDeviceOnly with a private ephemeral URLSession jar.
|
||||||
The emulator regression was observed failing when the main-frame guard was
|
- Bounded JSON reads, deadlines and no offline/ambiguous-write retry queue.
|
||||||
deliberately removed, then rerun with the fix restored.
|
- Native permission-aware controls, destructive-action confirmation and server
|
||||||
- TLS failures cancel by default. Native download redirects are refused before
|
validation; partial update payloads preserve fields the native editor cannot edit.
|
||||||
cookies can be replayed to another origin. Bootstrap requests use neither
|
- No WebView/WKWebView in either shipping source tree. Legacy tests do not prove
|
||||||
cookies nor automatic redirects and have bounded metadata reads/timeouts.
|
this client's behavior; explicit native tests and source invariants are required.
|
||||||
- Files use explicit system selection/content URIs; no filesystem or storage
|
|
||||||
permission is granted to web content. Blob exports have no native JS bridge.
|
|
||||||
- Complete Android browsing-data deletion uses WebStorageCompat, with OS app
|
|
||||||
reset for engines without that capability. WebStorage.deleteAllData alone was
|
|
||||||
insufficient for service-worker CacheStorage/IndexedDB and is not relied upon.
|
|
||||||
- iOS server erase replaces the WKWebView, not only its URL, eliminating old
|
|
||||||
history/back-forward contexts as well as persistent website data.
|
|
||||||
- iOS metadata uses typed decoding, rejecting numeric values masquerading as booleans.
|
|
||||||
- Native picker results are bound to the browsing generation/request. Android
|
|
||||||
rejects stale upload/download selections, revokes camera URI grants, and clears
|
|
||||||
capture cache on erasure. iOS ignores export-cancellation callbacks from an old
|
|
||||||
download. Apple-specific callback regressions have not run without Xcode.
|
|
||||||
- KGP was upgraded after OSV identified CVE-2026-53914 in the original build tool.
|
|
||||||
The final OSV scan found no listed advisories across 213 locked/direct Maven
|
|
||||||
coordinates and build plugins. Rescan after resolution/lock updates.
|
|
||||||
- The inspected release APK is not debuggable, rejects cleartext, disables backup
|
|
||||||
and trusts system CAs only. AndroidX's exported profile installer receiver is
|
|
||||||
protected by the system DUMP permission; app providers are not exported.
|
|
||||||
|
|
||||||
Release gates still requiring evidence:
|
## Remaining gates
|
||||||
|
|
||||||
- Actual Xcode typecheck, simulator, archive, physical-device and accessibility review.
|
1. Run Apple SDK typechecking, simulator/XCTest/UI and device checks; portable
|
||||||
- End-to-end IdP flows, especially providers that prohibit embedded agents; no
|
Foundation transport compilation is not SwiftUI/Security.framework validation.
|
||||||
browser-to-native session transfer is supported by the current upstream protocol.
|
2. Review persistent-cookie expiry/removal, TLS failures, redirects, CSRF refresh,
|
||||||
- iOS unknown-length download disk-pressure behavior; a post-download size check
|
expired sessions, background/recreation and stale-response isolation on devices.
|
||||||
is not a streaming quota. Verify file picker/camera cancellation on real devices.
|
3. Review migrations from the prototype: browser sessions are never imported and
|
||||||
- Android file-picker/camera/rotation while a picker is outstanding; cancellation
|
OS website data may remain until app-data reset/reinstall.
|
||||||
on process death intentionally loses the selection, never silently retries it.
|
4. Complete missing auth/provider protocols and permission/role scenarios before
|
||||||
- Offline sign-out/account switching, stale-worker updates and server erasure on
|
claiming native authentication parity, particularly SSO-only deployments.
|
||||||
current WebView/WKWebView versions. Upstream tests are not native device proof.
|
5. Implement/review files, notifications, offline storage and additional modules
|
||||||
- Reverify final signed release manifests, signing, store ownership, private vulnerability contact
|
as actual native capabilities; do not restore the wrapper as a shortcut.
|
||||||
and applicable privacy disclosures. No claim that all vulnerabilities are absent.
|
6. Independently review the new UI/state/transport code, actual signed artifacts,
|
||||||
|
accessibility, supported OS matrix and runner trust before distribution.
|
||||||
|
|
||||||
|
The owner-authorized signing configuration exists privately but its workflow
|
||||||
|
changes are intentionally parked. A signed incomplete client is not a completed
|
||||||
|
native product. Refer to [native parity](native-parity.md) before release work.
|
||||||
@@ -1,70 +1,41 @@
|
|||||||
# Server compatibility and authentication
|
# Native server compatibility
|
||||||
|
|
||||||
Source reference: upstream 2.78.0 revision
|
Reference: Yuvomi 2.78.0 at
|
||||||
`10bfef7686ed7303b4c74c7fcc55a5eb16356c9d`. No general version range has been
|
`10bfef7686ed7303b4c74c7fcc55a5eb16356c9d`. No general server-version range or
|
||||||
certified. Anonymous bootstrap metadata deliberately omits the exact version;
|
complete native feature compatibility is certified.
|
||||||
native probing verifies shape, not an invented minimum-version comparison.
|
|
||||||
|
|
||||||
Use `https://family.example.com` or `https://family.example.com:8443`, backed by a
|
Enter a root HTTPS hostname, optionally with a custom port. HTTP, embedded
|
||||||
root-hosted Yuvomi installation and a valid system-trusted certificate. Operators
|
credentials, query/fragment configuration and subpath deployments are rejected.
|
||||||
should set `SESSION_SECURE=true`, correct `BASE_URL`, and correct proxy trust.
|
Use a valid system-trusted TLS certificate and reachable VPN/LAN connectivity.
|
||||||
Private servers are supported through reachable HTTPS/VPN, not TLS bypasses.
|
No certificate bypass or proprietary mobile service is introduced.
|
||||||
International hostnames should be entered in ASCII/punycode for both platforms.
|
|
||||||
|
|
||||||
Root-relative assets, API endpoints, cookie paths, callback redirects and worker
|
The native client probes the real public `/api/v1/version` and
|
||||||
registration mean `/yuvomi/` subpaths are not supported by the inspected source.
|
`/api/v1/auth/oidc/config` shapes. Anonymous metadata does not disclose the server
|
||||||
Use a dedicated hostname. Reverse proxies must pass `/api/v1/*`, cookies, HTML,
|
version. An authentication proxy returning redirects/HTML instead of those JSON
|
||||||
JavaScript and the service worker consistently. An external authentication proxy
|
contracts is unsupported, not silently treated as a valid Yuvomi API.
|
||||||
that intercepts bootstrap calls is rejected with a connection error; it is not
|
|
||||||
silently identified as a Yuvomi server.
|
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
Password login, TOTP/recovery codes, password reset, invitations, server-side
|
The implemented native slice uses setup/password login, the existing two-factor
|
||||||
session expiry/revocation and logout remain upstream web flows. No native code
|
verification endpoint, `/auth/me`, session cookies, CSRF headers and logout.
|
||||||
stores the password, supplies a CSRF bypass, or extends an expired session.
|
Passwords are not stored. Native session persistence is separate from browser
|
||||||
Backgrounding does not clear cookies. Native server erasure does not revoke a
|
storage and protected by the platform keystore/keychain.
|
||||||
remote session; use Yuvomi logout first or revoke sessions server-side.
|
|
||||||
|
|
||||||
### OIDC: local fixture verified; real-provider validation pending
|
**Native SSO is not implemented yet.** The old wrapper's local-IdP WebView result
|
||||||
|
does not apply to this client. The existing server protocol does not provide a
|
||||||
|
generic browser-to-native session exchange for arbitrary self-hosted hosts; a
|
||||||
|
reviewed solution is required. SSO-only deployments cannot currently use this
|
||||||
|
native preview. Reset and invitation workflows also remain pending.
|
||||||
|
|
||||||
The initiating Yuvomi session contains OIDC state, nonce and PKCE verifier. When
|
Only initial dashboard/tasks/notes/shopping capabilities are implemented; see the
|
||||||
the server redirects to an identity provider, native consent offers an isolated
|
[parity tracker](native-parity.md) for precise gaps. The complete server UI is not
|
||||||
web sign-in window sharing the OS website cookie store. HTTPS-only redirects
|
embedded to fill those gaps. Read-only and denied module permissions affect
|
||||||
can return to the server callback; the final same-origin page returns to the main
|
native controls; the server remains the enforcement point.
|
||||||
view. No app-capability handlers or JS bridge are installed in that auth window.
|
|
||||||
|
|
||||||
Some providers (including configurations that prohibit embedded user agents)
|
## Notifications, files and offline
|
||||||
require a system browser. **Those cannot sign the native view in with upstream's
|
|
||||||
current protocol.** Use Server settings -> Open server in browser, and sign in
|
|
||||||
there for an independent browser session. Opening only the external authorization
|
|
||||||
link in a browser does not transfer the initiating cookie. Browser cookies are
|
|
||||||
never copied into the app, and custom-scheme callbacks are not fabricated.
|
|
||||||
|
|
||||||
The API 35 integration suite completes a native isolated-window round trip with
|
Native remote push, uploads/camera/download/export and offline caching/editing
|
||||||
a local test IdP, real RS256 ID tokens, nonce and S256 PKCE. No external
|
are not current native capabilities. The old wrapper's file handlers and the
|
||||||
IdP/developer account was supplied. Validate the actual provider, including
|
PWA service worker are not part of the native renderer. No fake registration or
|
||||||
cross-site cookies, cancellation, errors, TOTP and account linking, before relying
|
automatic offline mutation replay is supplied. Optional existing server-side
|
||||||
on that deployment. iOS authentication has not run against Apple SDKs. A native
|
ntfy/Gotify/email integrations remain independently operated upstream features.
|
||||||
browser handoff would require an independently reviewed upstream protocol; no
|
|
||||||
such upstream change is included or published.
|
|
||||||
|
|
||||||
Android generated exports require a current WebView supporting document-start
|
|
||||||
scripts and are capped at 25 MB. A bounded Blob registry preserves a generated
|
|
||||||
file even when upstream immediately revokes its object URL; it does not fetch
|
|
||||||
blob URLs or alter the server's CSP. HTTPS file downloads are capped at 100 MB.
|
|
||||||
Update the system WebView if generated exports are unavailable on an old engine.
|
|
||||||
|
|
||||||
## Notifications and offline
|
|
||||||
|
|
||||||
Upstream implements Web Push and optional ntfy/Gotify/webhook/email channels.
|
|
||||||
Embedded web views do not supply a portable native push subscription. This app
|
|
||||||
has **no native remote-push claim**, no Firebase/APNs secrets, no background
|
|
||||||
polling service, and no fake notification-registration UI. Configure an existing
|
|
||||||
optional upstream ntfy/Gotify channel and its client if desired. No centralized
|
|
||||||
service is required by this application.
|
|
||||||
|
|
||||||
Upstream service-worker caching is read-only, allow-listed, and versioned.
|
|
||||||
Mutations/authentication remain online. Platform-specific cache/resume behavior
|
|
||||||
and offline account switching still need device validation. Do not rely on offline
|
|
||||||
editing, synchronization, or closed-app push in this native development build.
|
|
||||||
+58
-119
@@ -1,92 +1,60 @@
|
|||||||
# Validation status
|
# Native validation
|
||||||
|
|
||||||
**Partially verified development software, not production-ready.**
|
**Incomplete native rebuild; not full PWA parity and not production-ready.**
|
||||||
Local validation date: 2026-10-21. No unexecuted iOS application test, hosted CI
|
The old browser results are [historical only](legacy-wrapper-validation.md).
|
||||||
run, production signing, or store publication is represented as completed.
|
|
||||||
|
|
||||||
## Executed evidence
|
The new shipping surfaces are Android Compose and iOS SwiftUI. Current native
|
||||||
|
tests are in `androidTestNative` / `androidTestNativeIntegration`, JVM native policy
|
||||||
|
tests, and Swift production contracts/transport tests. Archived WebView tests are
|
||||||
|
not included in the native suites or counted toward native completion.
|
||||||
|
|
||||||
- Android debug APK and unsigned release APK/AAB built successfully; both
|
## Executed locally — 2026-10-21
|
||||||
`lintDebug` and `lintRelease` passed. JVM security/picker-policy tests: **7 passed,
|
|
||||||
zero failures/skips**.
|
|
||||||
- Android API 35 regular emulator suite: **6 passed, zero failures/skips**.
|
|
||||||
This covers onboarding, invalid URLs, background/resume, hardened settings,
|
|
||||||
cross-origin POST/subresource isolation, opaque-page Blob rejection and activity
|
|
||||||
recreation. Its permission test checks that the API 37 permission UI is absent;
|
|
||||||
it is **not** evidence of API 37 permission grant/denial behavior.
|
|
||||||
- Unmodified pinned upstream ran behind a temporary HTTPS reverse proxy.
|
|
||||||
Bootstrap metadata, password login, Secure/HttpOnly/SameSite cookies, persistent
|
|
||||||
session, CSRF rejection, logout/revocation passed in the harness.
|
|
||||||
- Android's extended real-server scenario exercises login, HttpOnly cookies,
|
|
||||||
document upload via upstream fetch, native FileTransfer output, bounded Blob
|
|
||||||
export, background/resume, recreation, CSRF-protected logout, revocation,
|
|
||||||
recovery, isolated OIDC return and back navigation. It does not automate the OS
|
|
||||||
camera/document destination picker or prove every upstream module works.
|
|
||||||
Two consecutive API 35 runs have **7 passed, zero failures/skips each**, including the
|
|
||||||
six regular security/onboarding cases and this real-server scenario.
|
|
||||||
- The cross-origin POST regression was deliberately observed failing without its
|
|
||||||
guard. The production guard was restored and the API 35 regression passes.
|
|
||||||
- Portable Swift production-policy tests: 7 passed (URL and typed metadata).
|
|
||||||
All Swift sources passed format lint and parsing with Swift 6.2.1 on Linux.
|
|
||||||
The portable package excludes BrowserModelTests. This does not build iOS.
|
|
||||||
- Selected upstream suites ran successfully: cookie-secure-flag (4),
|
|
||||||
session-sliding (8), two-factor (22), password-reset (24), sw-api-cache (42).
|
|
||||||
Upstream's plain OIDC script also exited successfully. These are upstream tests,
|
|
||||||
not evidence of a provider round-trip or native push support.
|
|
||||||
- The HTTPS harness independently passed upstream OIDC discovery, RS256 ID-token
|
|
||||||
signature/nonce validation, S256 PKCE exchange and session creation with a local
|
|
||||||
test IdP. The fixture checks single-use codes, exact redirect URIs and OAuth
|
|
||||||
Basic client authentication. Loopback hosts/ports and automatic fixture consent
|
|
||||||
are not representative of every provider's cross-site/embedded-agent policies.
|
|
||||||
- OSV: no listed advisories for **213** locked/direct Maven coordinates and build
|
|
||||||
plugins at scan time. This is not a guarantee that no vulnerabilities exist.
|
|
||||||
- ktlint 1.7.1, actionlint 1.7.7, repository invariants, Python compilation,
|
|
||||||
Node syntax and shell syntax checks passed. JUnit-verifier regression suite:
|
|
||||||
**8 passed**, including rejection of absent, empty, malformed, insufficient,
|
|
||||||
failed, errored and skipped evidence.
|
|
||||||
- Release APK inspection confirms API 26 minimum / API 37 target, no debuggable
|
|
||||||
flag, backups and cleartext disabled, system-only certificate trust. Exported
|
|
||||||
entry points are the launcher and AndroidX ProfileInstallReceiver protected by
|
|
||||||
the system DUMP permission; file/startup providers are not exported. Debug APK
|
|
||||||
signature verifies; release APK/AAB are unsigned. Collected archives contain no
|
|
||||||
fixture CA/key or signing-key files.
|
|
||||||
|
|
||||||
## Emulator limitations and retry evidence
|
| Check | Observed result |
|
||||||
|
| --- | --- |
|
||||||
|
| Android JVM tests | 10 passed; zero failed/skipped |
|
||||||
|
| Native Compose UI/security suite, API 35 emulator | 6 passed; zero failed/skipped |
|
||||||
|
| Real-upstream native integration suite | 7 passed; zero failed/skipped (the same 6 onboarding tests plus 1 multi-step real-server scenario) |
|
||||||
|
| Native scenario | Login/dashboard, activity recreation, task/note/list/item creation and API readback, redirect refusal, logout and vault erasure |
|
||||||
|
| Integration screenshot export | Successful AGP test-output collection; native dashboard PNG opened and visually confirmed nonblank, synthetic data only |
|
||||||
|
| Android lint | Debug and release passed; newer-version recommendations remain informational |
|
||||||
|
| Android packages | Debug APK and unsigned release APK/AAB built successfully |
|
||||||
|
| Swift portable suite | 16 passed; actual Foundation transport/contracts and URL/metadata policy, not Apple UI/Keychain execution |
|
||||||
|
| Swift formatting/parsing | Strict format lint and parsing passed, including Apple-only sources |
|
||||||
|
| Script regressions | 10 runner-preflight, 8 JUnit-evidence and 5 screenshot-output tests passed |
|
||||||
|
| Repository/workflows | Source invariants, Python compilation, diff whitespace and actionlint for all 3 Gitea workflows passed |
|
||||||
|
| OSV | No listed advisories for 266 locked/direct Maven coordinates and plugins; not a security audit |
|
||||||
|
|
||||||
Earlier extended-suite attempts crashed the host emulator with SIGSEGV under
|
Environment: Linux/WSL, OpenJDK 17.0.20.1, Gradle 9.6.0, AGP 9.4.1,
|
||||||
software/off GPU modes. Host-GPU mode remained running and produced actionable
|
Kotlin/Compose compiler 2.4.21, API 35 `sdk_gphone64_x86_64` emulator, Swift 6.2.1.
|
||||||
JUnit failures: an OIDC-return synchronization timeout, followed by an outage
|
The host-only Tink upgrade to 1.15.0 removes the observed obsolete generated
|
||||||
assertion that incorrectly assumed the upstream worker could not serve its cached
|
protobuf warning; the final Android validation log has no such warning.
|
||||||
app shell, then a document-readiness race after recreation. Tests now verify the
|
|
||||||
loaded JavaScript origin, wait for the sign-in window to close, retry only a probe
|
|
||||||
lost to document replacement and exercise recovery through uncached metadata.
|
|
||||||
The completed retry passes all seven tests without disabling the worker or
|
|
||||||
weakening production TLS/CSP/origin policies.
|
|
||||||
|
|
||||||
API 37 attempts encountered broken package/activity services and locked
|
The first integration attempt missed the scrolled-off login button. Later,
|
||||||
credential-encrypted storage. **No API 37 runtime pass is claimed.**
|
post-uninstall screenshot retrieval failed, and the first compositor capture was
|
||||||
|
black. The final test scrolls the real button, uses native-window capture with a
|
||||||
|
nonblank-pixel assertion and writes through `PlatformTestStorageRegistry` for AGP
|
||||||
|
collection. The latest complete harness exits successfully, not just its JUnit
|
||||||
|
subprocess. Ordinary builds retain screenshot protection.
|
||||||
|
|
||||||
Local logs and reports live in `/home/neste/yuvomi-build/`; test XML is under
|
The unmodified pinned upstream HTTPS/OIDC protocol fixture also passed TLS trust,
|
||||||
`app/outputs/androidTest-results/connected/`. Earlier failing JUnit snapshots are
|
metadata, cookies, CSRF and remote revocation checks. Its IdP exchange is **not
|
||||||
preserved as `integration-host-gpu-oidc-race.xml` and
|
native SSO**: the native client refuses the redirect and SSO remains pending.
|
||||||
`integration-host-gpu-sw-cache.xml`, plus
|
|
||||||
`integration-host-gpu-document-ready.xml`. Passing evidence is preserved in
|
|
||||||
`integration-api35-first-pass.xml` and `integration-api35-repeat-pass.xml`; logs are
|
|
||||||
`upstream-integration-final-retry.log` and `upstream-integration-repeat.log`.
|
|
||||||
These files are local evidence, not published
|
|
||||||
artifacts or a hosted CI result.
|
|
||||||
|
|
||||||
Test environment: JDK 17.0.20.1, Node 22.22.1, Python 3.14.4, Android Emulator
|
Evidence paths in the local external build directory:
|
||||||
37.2.12, API 35 x86_64 Google APIs image, WebView 124.0.6367.219. The old bundled
|
|
||||||
WebView is useful compatibility evidence, not a recommendation to use an unpatched
|
|
||||||
engine; a current engine/device run remains mandatory.
|
|
||||||
|
|
||||||
## Artifacts
|
- `app/test-results/testDebugUnitTest/`
|
||||||
|
- `app/outputs/androidTest-results/connected/{debug,integration}/`
|
||||||
|
- `app/outputs/native-screenshots/native-dashboard.png`
|
||||||
|
- `app/reports/lint-results-{debug,release}.html`
|
||||||
|
- Logs: `/home/neste/yuvomi-native-validation.log`,
|
||||||
|
`/home/neste/yuvomi-native-integration-final.log`,
|
||||||
|
`/home/neste/yuvomi-native-swift.log`.
|
||||||
|
|
||||||
Ignored `artifacts/android/` contains the development-signed debug APK and unsigned
|
No Apple SDK application build, simulator UI test or physical-device result is
|
||||||
release APK/AAB, `SHA256SUMS`, `build-info.json` and manifest/policy/signature
|
claimed from these Linux runs. The modified Mac bootstrap and remote APK upload
|
||||||
inspection evidence. No integration APK is collected. No IPA or Apple archive
|
still require inspection of the next actual Gitea run. Prior remote emulator jobs
|
||||||
exists. See [Android build](build-android.md) for repeatable collection commands.
|
failed KVM preflight; the prerequisite was not weakened or counted as passing.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
@@ -97,47 +65,18 @@ swift test --package-path ios
|
|||||||
swiftc -frontend -parse ios/Sources/*.swift ios/Tests/*.swift ios/UITests/*.swift
|
swiftc -frontend -parse ios/Sources/*.swift ios/Tests/*.swift ios/UITests/*.swift
|
||||||
python3 scripts/check-repository.py
|
python3 scripts/check-repository.py
|
||||||
python3 scripts/check-dependencies.py
|
python3 scripts/check-dependencies.py
|
||||||
python3 scripts/test-verifier.py
|
python3 scripts/lint-workflows.py /path/to/actionlint
|
||||||
python3 scripts/collect-android-artifacts.py
|
|
||||||
git diff --check
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This environment is Linux/WSL. Android SDK and a KVM emulator were installed for
|
On the local WSL checkout use `YUVOMI_BUILD_DIR=/home/neste/yuvomi-native-build`
|
||||||
real execution. Build output relocation was needed because the Windows mount
|
and the SDK paths from [continuation](continuation.md). Select only the authorized
|
||||||
rejects some Gradle POSIX metadata operations. Swift's Linux toolchain was
|
test emulator with `ANDROID_SERIAL=emulator-5554`; unrelated/unauthorized attached
|
||||||
installed for portable tests. No macOS, Xcode, Apple simulator or physical device
|
devices are not test targets.
|
||||||
is available; no iOS build/archive/UI result is claimed.
|
|
||||||
|
|
||||||
## Mandatory remaining evidence
|
## External gates
|
||||||
|
|
||||||
- Run Xcode build, XCTest/UI tests and unsigned archive on macOS; fix any compiler
|
Apple SDK builds, real supported devices/current engines, Android API 37, native
|
||||||
or runtime issues. The app has **not** yet been typechecked against Apple SDKs.
|
SSO/reset/invite protocols, permission/role cases, files/offline/notifications,
|
||||||
- Validate real IdPs: cancellation, account linking, TOTP after OIDC, and embedded
|
complete module and settings parity, visual baselines, accessibility and human
|
||||||
provider policy. Browser-only providers have no native-session handoff upstream.
|
security review remain open. Missing modules are listed in
|
||||||
- Real-device camera/document picker cancellation, file MIME cases, rotation with
|
[native parity](native-parity.md), not silently represented as working.
|
||||||
an outstanding picker, network loss/reconnect, process kill/memory pressure,
|
|
||||||
session expiry/revocation, OS backup, and offline account isolation.
|
|
||||||
- Android 17 private-network permission grant/denial/revocation on a matching OS.
|
|
||||||
Also run minimum-supported API 26 and a current OS/WebView device matrix.
|
|
||||||
- VoiceOver/TalkBack, large text, contrast, keyboard/safe areas, reduced motion,
|
|
||||||
light/dark appearance and responsive web modules on actual supported devices.
|
|
||||||
- Successful CI runs on the configured Gitea runners, private security
|
|
||||||
reporting contact, human security review, store ownership and production signing.
|
|
||||||
|
|
||||||
No Firebase/APNs registration, closed-app push, offline editing, App Store approval,
|
|
||||||
signing, publication or physical-device validation is claimed. See `SECURITY.md`
|
|
||||||
and `docs/security-review.md` for residual limitations.
|
|
||||||
Resume work using [maintainer continuation](continuation.md).
|
|
||||||
|
|
||||||
## Gitea runner adaptation
|
|
||||||
|
|
||||||
Workflows now live in `.gitea/workflows/` and target the supplied `ubuntu-latest`
|
|
||||||
pool and native `macos-arm64` M4 Pro runner. Local workflow grammar lint (Gitea URL
|
|
||||||
syntax normalized), repository invariants, shell/Python syntax, ten mocked runner
|
|
||||||
preflight regressions and eight evidence-verifier regressions pass. SHA-256 Git
|
|
||||||
initialization/fetch was exercised locally; the pinned XcodeGen archive's checksum
|
|
||||||
and native arm64 slice were verified. These are not remote runner execution or
|
|
||||||
Apple SDK results. See [runner requirements](ci-runners.md); the local emulator
|
|
||||||
preflight currently rejects unavailable/inaccessible KVM as designed. Original
|
|
||||||
application build evidence above remains historical and is not a rebuild of the
|
|
||||||
workflow-only changes.
|
|
||||||
Reference in new issue
Block a user