Every shopping item now gets a visual like in Bring: a product emoji on
a softly tinted category tile.
- ItemVisuals.kt: pure client-side classifier. German dictionary
(~180 entries) maps item names to emoji + one of 13 categories
(produce, drinks, bakery, dairy, meat&fish, frozen, pantry, sweets,
household, drugstore, baby, pet, other), each with an accent color.
Longest-keyword-first matching so compounds resolve to their most
specific entry (Wassermelone is produce, not a drink); juice
compounds (Apfelsaft, Orangensaft, ...) are listed explicitly because
their fruit prefix is longer than 'saft'. Unknown items fall back to
the generic cart on neutral grey. Works fully offline, nothing leaves
the device.
- ListDetailScreen: emoji tile in every item row, emoji in the
autocomplete suggestions dropdown, and a live emoji preview as the
text field's leading icon while typing.
- ItemVisualsTest: longest-match priority, case/whitespace
insensitivity, fallbacks, category coverage.
Verified: assembleDebug + unit tests green (JDK 21).
Document the four features that landed on main in b44bc8c..85c790e:
- AGENTS.md: post-MVP section now covers server-driven auth discovery
(GET /api/config, AUTH_PASSWORD_ENABLED 403 enforcement,
OIDC_GENERIC_DISPLAY_NAME), the settings screen with GET/PUT /api/me,
and the critical Android sync/data-safety fixes (pull-all-lists,
client HLC tick per server op, no destructive migration, ProGuard
rules). Repo structure updated (httpapi config.go/me.go, ui/settings),
roadmap entries added, open-points list extended with test backlog for
the new endpoints.
- API.md: new sections for GET /api/config (public) and GET/PUT /api/me;
403 responses documented for register/login when password auth is off.
- SYNC.md: client pull loop (every tracked list, op_log pruning) and the
client HLC discipline (tick per incoming server op) that keeps LWW
correct across devices with skewed clocks.
- README: highlights for auth discovery/OIDC-only mode and the settings
screen.
Integration tests for the invite/join/membership feature that shipped
without any coverage:
- internal/store/liststore_test.go: CreateList adds owner as member with
invite code, GetLists returns owned+joined but not foreign lists,
GetList access control (owner/member yes, stranger and soft-deleted no),
JoinByInviteCode normalization/idempotency/role-keeping, lazy invite
code generation. Runs against TEST_DATABASE_URL, skips otherwise.
- internal/httpapi/api_test.go: full E2E over the real router — register,
create list (code in response), invite endpoint, join (lowercase),
cross-member op push/pull sync, stranger gets 404 on every list
endpoint, invalid code 400, idempotent re-join, and 401 gating of all
protected routes.
- lists.go Invite handler: store errors now map through apiError, so
non-members get 404 instead of 400 (consistent with Get/Push/Pull).
Docs updated to the actual post-MVP state: AGENTS.md (post-MVP features,
repo structure, roadmap with open points like join rate limiting),
API.md (join/invite endpoints, invite_code fields, membership rules),
SYNC.md (shared lists section), README (local-only default, sharing,
integration test recipe).