aboutsummaryrefslogtreecommitdiffstats
path: root/AGENTS.md
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-04 18:08:01 +0100
committerDanilo M. <danix@danix.xyz>2026-11-04 18:08:01 +0100
commitca69bd81057fc8a9f65ff7e2f1d874697df8a6cc (patch)
tree02730c06ff21d9bd132c4d87a7bf4b7c3a0f1fee /AGENTS.md
parent0208c067c6bf31d31b735c23e037bc18227f4083 (diff)
downloadHardenedPass-ca69bd81057fc8a9f65ff7e2f1d874697df8a6cc.tar.gz
HardenedPass-ca69bd81057fc8a9f65ff7e2f1d874697df8a6cc.zip
docs: record the finished Compose overhaul
AGENTS.md drops the compose branch exception, describes the Compose UI and its activities, updates the emulator notes (serial pinning, prefixed helpers, Compose nodes, which windows are FLAG_SECURE, waiting for user storage after boot, FAB content-desc, text field clearing, run-as quoting) and the last device runs, and records why Material Components (Views) and fragment-ktx stay. The spec is marked complete with what was removed and kept, and says the merge waits for the maintainer's phone test; CONTRIBUTING.md no longer asks for view binding. The cleanup plan's emulator pass gets the harness fixes found while running it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'AGENTS.md')
-rw-r--r--AGENTS.md54
1 files changed, 40 insertions, 14 deletions
diff --git a/AGENTS.md b/AGENTS.md
index f2e32456..47028103 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -14,6 +14,12 @@ Modules: `app` (UI, git sync, autofill service), `autofill-parser`, `crypto:comm
`crypto:pgpainless`, `format:common`, `passgen:diceware`, `passgen:random`, `ui:compose`,
`coroutine-utils`. Build conventions live in `build-logic/`.
+The UI is Jetpack Compose with Material 3. `MainActivity` hosts every screen in one `NavHost`
+(list, entry, editor, setup, settings); `LaunchActivity` is the only exported activity. The
+autofill service starts its four activities (`AutofillFilterView`, `AutofillDecryptActivity`,
+`AutofillSaveActivity`, `AutofillPublisherChangedActivity`) directly, so they stay separate and
+draw with the same theme.
+
`applicationId` is `xyz.danix.hardenedpass` (debug: `.debug` suffix, label "HardenedPass
Debug"), so it installs next to upstream's `app.passwordstore` and never updates over it. The
Kotlin package stays `app.passwordstore`; renaming it is churn with no user-visible effect.
@@ -21,11 +27,7 @@ Keep "GrapheneOS" out of the app name: it is that project's trademark.
## Repository layout and remotes
-- `master` is the only long-lived branch. Upstream's `develop` was renamed; do not recreate it.
-- Temporary exception: the Compose UI overhaul
- (`docs/superpowers/specs/2026-11-02-compose-ui-overhaul-design.md`) lives on `compose` until
- it is complete; nothing is released from it. `master` stays releasable (public suffix list,
- hotfixes). Remove this bullet when `compose` merges.
+- `master` is the only branch. Upstream's `develop` was renamed; do not recreate it.
- `origin` fetches from the maintainer's own git server (the main repository) and pushes to it
and to the GitHub fork (`danixland/HardenedPass`) in one `git push`.
GitHub is a push mirror: never create commits on GitHub (bots, web edits), they would
@@ -69,10 +71,23 @@ in `local.properties`:
$ANDROID_HOME/emulator/emulator -avd aps-test -no-window -no-audio -no-boot-anim \
-no-snapshot-save -gpu swiftshader_indirect &
- ./gradlew installDebug
-
-Drive it with `adb shell input`, `uiautomator dump` and `screencap`. Decrypt screens set
-`FLAG_SECURE`, so screenshots of them are black; read them from the `uiautomator` dump.
+ ./gradlew :app:installDebug
+
+If a physical device is connected too, `export ANDROID_SERIAL=emulator-5554` first, so every
+`adb` and Gradle install command targets the emulator. Agent shells keep no functions or
+variables between calls: keep that export and any helpers in a sourced file, and prefix helper
+names (`e2e_pass`, not `pass`, which is the real `pass` and reaches a real store). Drive it with
+`adb shell input`, `uiautomator dump` and `screencap`; Compose nodes carry `text` and
+`content-desc` in the dump, no resource ids, so match on those. FABs ("Import PGP key", "New
+entry") carry only `content-desc`, and the list's search bar is itself an `EditText`. The entry
+view, the editor and its generator sheet, the proxy screen, the passphrase dialogs and the
+autofill decryption and save windows set `FLAG_SECURE`, so screenshots of them are black; read
+them from the `uiautomator` dump. After boot, wait until the keyguard is dismissed and user
+storage is unlocked before `adb uninstall` or `push-keys`: earlier, uninstall fails with
+`DELETE_FAILED_INTERNAL_ERROR` and `/sdcard/Download` does not exist yet. In a Compose text
+field, wait about a second after the tap before clearing it (Ctrl+A, DEL), or the clear misses.
+`adb shell run-as <pkg> sh -c '...'` needs the whole command quoted as one `adb` argument
+(`adb shell "run-as <pkg> sh -c '...'"`), or the device shell splits it.
Fingerprint: `adb emu finger touch 1` after enrolling one in Settings (needs a lock PIN:
`adb shell locksettings set-pin 1234` on the emulator only). Disable animations
(`settings put global animator_duration_scale 0`, same for `transition_` and `window_`)
@@ -85,8 +100,11 @@ worktree with `~/.android/debug.keystore`, so an in-place upgrade between them n
re-signing.
Autofill cannot be tested on the emulator image: Settings is denylisted in
-`OreoAutofillService`, and the only browser (WebView Shell) is not a trusted browser. Use a
-real device with a trusted browser (e.g. Firefox) instead:
+`OreoAutofillService`, and the only browser (WebView Shell) is not a trusted browser. Its
+activities are not exported; after `adb root` (the AOSP image allows it), `am start -n` opens the
+picker, the publisher warning and the save editor with test extras, but not a real decryption
+(it needs a client state `Bundle`). Use a real device with a trusted browser (e.g. Firefox)
+instead:
- `adb reverse tcp:2222 tcp:2222` lets the device clone `ssh://git@127.0.0.1:2222/...` from the
e2e server over USB; serve a local login page the same way (`python3 -m http.server` on
@@ -102,9 +120,10 @@ real device with a trusted browser (e.g. Firefox) instead:
- Only read screens of the debug app, the test page and the autofill UI; the device holds the
owner's real data.
-Last full device run (2026-11-02): clone over SSH, PGP import, decrypt, TOTP, create and push,
-conflict recovery, hard reset, fingerprint unlock (emulator) and Firefox autofill (tablet) all
-passed.
+Last full emulator run (2026-11-04, Compose UI): clone over SSH, PGP import, decrypt, TOTP,
+create and push, conflict recovery (abort rebase, push a new branch), hard reset and
+fingerprint unlock passed. Last Firefox autofill run on the tablet: 2026-11-04 (fill, passphrase
+cache rule, no keys flow, picker, settings dialog), all passed.
## Verified facts and gotchas
@@ -122,6 +141,13 @@ passed.
- `LaunchActivity` is exported and forwards `FILE_PATH` to `MainActivity` (not exported) only
after `isFileInRepo` checks it canonically resolves inside the store; `MainActivity` opens it as
`EntryRoute`, whose destination checks it again before decrypting.
+- Material Components (Views) stays after the Compose overhaul: the window themes derive from
+ `Theme.Material3.DayNight` (the AppCompat activities need it), and the git operations' View
+ dialogs (`BaseGitActivity`, `GitOperation`, `CredentialFinder` with
+ `git_credential_layout.xml`, `BreakOutOfDetached`, `StoreActions`), `DynamicColors` and the
+ `snackbar` helper use it. `oreo_autofill_dataset.xml` stays a layout: fill suggestions are
+ `RemoteViews` drawn by the system. `fragment-ktx` is declared only to pin `androidx.fragment`
+ (appcompat alone resolves an older one).
- sshj gets Ed25519 keys from Bouncy Castle: `SshjConfig.kt` pins `KeyFactory.Ed25519` to it at
provider position 1. Conscrypt from Android 14 mainline updates serves that factory with keys
sshj maps to `KeyType.UNKNOWN` ("Don't know how to encode key"), breaking every Ed25519 host