Commit graph

274 commits

Author SHA1 Message Date
dd9c97a57a feat(site): human-language 'what you can do' features section
All checks were successful
ci / test-commons-core (push) Successful in 46s
ci / analyze (push) Successful in 1m23s
site / deploy (push) Successful in 31s
ci / test-app-seeds (push) Successful in 5m52s
Add a features section to the landing home (EN/ES) that describes what
Tane does by intent, not mechanism: inventory, care & calendar, labels &
backup, and the neighbourly sharing layer (offers, chat, trust, plantaré,
sync). Follows the existing pillars/values pattern (front-matter data +
template + CSS, RTL-safe). Reframe the beta status copy so the sharing
layer reads as 'arriving, in beta' rather than 'being built'.
2026-07-17 12:52:47 +02:00
75098b8029 docs(about): age range 10-99, link 'translate' to Weblate
All checks were successful
ci / test-commons-core (push) Successful in 43s
ci / analyze (push) Successful in 1m26s
site / deploy (push) Successful in 27s
ci / test-app-seeds (push) Successful in 5m47s
2026-07-17 12:23:45 +02:00
e321447f9d chore(i18n): regenerate strings.g.dart (slang)
All checks were successful
ci / analyze (push) Successful in 2m15s
ci / test-commons-core (push) Successful in 1m6s
ci / test-app-seeds (push) Successful in 8m25s
2026-07-17 09:25:20 +02:00
d27dc1c553 chore(release): v0.1.1 (+3) — GMS-free build
Some checks failed
ci / test-commons-core (push) Successful in 43s
ci / analyze (push) Successful in 1m23s
site / deploy (push) Successful in 25s
ci / test-app-seeds (push) Has been cancelled
release / android (push) Failing after 10m57s
Bumps to 0.1.1+3 (versionCode 3). Adds CHANGELOG [0.1.1], fastlane
changelogs (en-US, es-ES) for versionCode 3, and a 0.1.1 build entry in
the F-Droid recipe (commit v0.1.1, CurrentVersion/Code 3).
2026-07-17 09:19:16 +02:00
d0fabb80a9 fix(android): drop geolocator for a native LocationManager channel
Removes the geolocator dependency, which transitively embedded
com.google.android.gms.* (play-services-location) — proprietary classes
that F-Droid's scanner rejects. The optional coarse-location button now
talks to Android's own LocationManager over a small platform channel
(org.comunes.tane/coarse_location): permission prompt, single coarse fix
with a 12s timeout, last-known fallback, null on any failure. Behavior
is unchanged and the CoarseLocationProvider interface is preserved, so
the UI, i18n and widget tests need no changes.

Also sets dependenciesInfo.includeInApk/Bundle = false so the AGP
dependency-metadata block (also flagged by F-Droid) is not embedded.
Neither change affects the Google Play build.
2026-07-17 09:19:05 +02:00
7f1118a243 docs(fdroid): fix recipe for F-Droid CI (build chown, checkupdates, schema)
All checks were successful
ci / test-commons-core (push) Successful in 43s
ci / analyze (push) Successful in 1m24s
site / deploy (push) Successful in 25s
ci / test-app-seeds (push) Successful in 5m43s
- chown /opt/flutter to vagrant (build runs as non-root; fixes cache write)
- AutoUpdateMode: Version (drop invalid 'v%v' per schema)
- UpdateCheckMode: Tags v[\d.]+ + UpdateCheckData reading version from
  apps/app_seeds/pubspec.yaml (Flutter versionCode isn't a literal in gradle)
Validated locally: schema, lint, checkupdates (exit 0), and flutter build as vagrant.
2026-07-17 08:26:27 +02:00
ab66f2fdf1 docs(fdroid): fit categories (Inventory/Market) + versionCode 2
All checks were successful
ci / test-commons-core (push) Successful in 45s
ci / analyze (push) Successful in 1m28s
site / deploy (push) Successful in 29s
ci / test-app-seeds (push) Successful in 5m51s
Categories now Inventory + Market & Price + Science & Education (F-Droid has no
'Tools'; these match the app). Build entry and CurrentVersionCode bumped to 2 to
match the shipped 0.1.0 release. Description/screenshots come from the fastlane
metadata tree, not this recipe.
2026-07-17 07:31:47 +02:00
4fc343e57d Update gitignore 2026-07-16 22:21:27 +02:00
d8f5370220 fix(site): typo in SITE_DEST
Some checks failed
ci / analyze (push) Successful in 1m28s
ci / test-commons-core (push) Successful in 51s
ci / test-app-seeds (push) Successful in 7m42s
release / android (push) Failing after 17m6s
2026-07-16 21:42:25 +02:00
46e5148385 Trying to fix deploy
All checks were successful
ci / analyze (push) Successful in 1m19s
ci / test-commons-core (push) Successful in 44s
ci / test-app-seeds (push) Successful in 7m25s
2026-07-16 21:31:18 +02:00
1a49376d84 ci(site): disable auto-deploy (runner can't reach groucho over SSH)
All checks were successful
ci / analyze (push) Successful in 1m9s
ci / test-commons-core (push) Successful in 38s
ci / test-app-seeds (push) Successful in 5m40s
aaron routes to groucho via ada (ens18 down); the groucho->aaron data path drops
packets so the SSH banner never returns (TCP+ICMP ok). Left workflow_dispatch-only
until the network is fixed; deploy meanwhile via ansible tane-landing.yml.
2026-07-16 18:41:14 +02:00
89e3287146 ci(site): auto-deploy landing to groucho on push to main
All checks were successful
ci / analyze (push) Successful in 1m9s
ci / test-commons-core (push) Successful in 37s
ci / test-app-seeds (push) Successful in 6m4s
2026-07-16 16:45:20 +02:00
8e177ef00f feat(site): publish Google Play link now that the app is live
All checks were successful
ci / analyze (push) Successful in 1m8s
ci / test-commons-core (push) Successful in 38s
ci / test-app-seeds (push) Successful in 5m56s
Set playStoreURL so the store-badges partial renders the Google Play
badge (id=org.comunes.tane) on the landing page.
2026-07-16 16:20:37 +02:00
5bf06aa258 release: bump to 0.1.0+2 and add promote_production fastlane lane
All checks were successful
ci / analyze (push) Successful in 1m9s
ci / test-commons-core (push) Successful in 38s
ci / test-app-seeds (push) Successful in 5m48s
2026-07-16 15:40:26 +02:00
61f54cc0db ci(forgejo): turn off format gate, fix locale-fragile settings test
All checks were successful
ci / analyze (push) Successful in 1m9s
ci / test-commons-core (push) Successful in 41s
ci / test-app-seeds (push) Successful in 5m52s
Format: repo predates Dart 3.11's tall formatter (~128 files would need a
dedicated reformat commit); disable --set-exit-if-changed for now, keep
flutter analyze as the real gate.

Test: 'drawer Settings opens the settings screen' asserted find.text('Español'),
which only holds when the resolved locale is Spanish. Under AppLocale.en (as
set in the test) the tile reads 'English', so it failed under CI's non-Spanish
host locale. Assert by the language selector's Key + icon instead (locale-robust).
2026-07-16 12:21:27 +02:00
b6eae28234 ci(forgejo): manual git checkout instead of actions/checkout@v4
Some checks failed
ci / analyze (push) Failing after 30s
ci / test-commons-core (push) Successful in 45s
ci / test-app-seeds (push) Failing after 6m2s
The cirruslabs/flutter job image has no Node.js, so JS-based actions fail with
'exec: node: not found'. Check out with plain git over the internal forgejo:3000
URL + job token, keeping the workflows Node-free.
2026-07-16 11:32:08 +02:00
4cac56e3bb docs(release): note Forgejo Actions runner is missing on aaron + keystore alias
Some checks failed
ci / analyze (push) Failing after 15s
ci / test-commons-core (push) Failing after 29s
ci / test-app-seeds (push) Failing after 3s
aaron runs forgejo + jenkins but no act_runner, so workflows queue until a runner
is registered (or CI moves to Jenkins). Record that the keystore alias is tane-upload.
2026-07-16 03:15:18 +02:00
15eb9f7007 ci: port analyze/test gate to Forgejo Actions, retire .gitlab-ci.yml
git.comunes.org is Forgejo. Replicates the analyze + commons_core/app_seeds test
gate in .forgejo/workflows/ci.yml (per-push + PR). Dropped the GitLab-only Windows
job (no Forgejo Windows runner).
2026-07-16 03:07:07 +02:00
17d0ff1221 fix(release): port store publishing to Forgejo Actions (canonical remote is Forgejo)
git.comunes.org runs Forgejo Actions, not GitLab CI, so the tag-triggered
signed-AAB build + fastlane Play upload now lives in .forgejo/workflows/release.yml
(single job, no cross-job artifact passing). Removed the equivalent GitLab jobs;
.gitlab-ci.yml keeps only the analyze/test gate. Play service account is reused
from Ğ1nkgo. docs/release.md updated (Forgejo secrets).
2026-07-16 03:05:33 +02:00
eef99975bf feat(store): branded feature graphic (1024x500) + 512 store icon
Noto Sans wordmark on brand green (#2F7D34), white sprout, and the official
value tagline ('keep and share traditional seeds' / 'guarda y comparte...').
Generated by tool/gen_feature_graphic.py for en-US and es-ES.
2026-07-16 02:49:06 +02:00
fd6b9d5f0d feat(release): automate store publishing (fastlane supply + GitLab CI) and F-Droid recipe
- fastlane: Appfile/Fastfile/Gemfile with deploy_play lane (AAB -> Play internal track)
- CI: tag-gated build:android (signed AAB/APK from CI secrets) + deploy:play jobs
- F-Droid: fdroiddata build recipe at docs/fdroid/org.comunes.tane.yml
- Play compliance: Data Safety / content-rating answer sheet (docs/legal/internal)
- docs/release.md: automated tag-triggered flow, dedicated tane-upload keystore
- pubspec: description now mentions the market, not just the inventory
2026-07-16 02:42:47 +02:00
dc0d18562f fix(quick-add): wrap sheet action row to prevent overflow on small screens
The Cancel / Save-and-add-another / Save actions were a fixed Row that
could not shrink, so on narrow phones and long locales (es/pt/de/fr) the
buttons overflowed the right edge (the clipped 'Guardar'). Replace it with
an OverflowBar that wraps onto stacked, end-aligned lines when they don't
fit; move the added-count onto its own line above.

Guard it in small_screen_overflow_test.dart across the long locales.
2026-07-16 00:34:42 +02:00
5b64fe14b3 docs: de-link spike findings from spike/ code (moved to private repo) 2026-07-15 20:27:45 +02:00
2d4dec5304 docs(i18n): correct site Weblate format to go-i18n-json-v2
The object-form go-i18n JSON ({"key":{"other":...}}) is parsed by Weblate's
go-i18n-json-v2 format, not go-i18n-json (which expects a top-level array).
2026-07-15 19:46:16 +02:00
7150e337eb i18n(site): convert Hugo i18n TOML->go-i18n JSON for Weblate
Weblate has no native Hugo-TOML format. The strings are already the go-i18n
structure ([key]/other=), so convert site/i18n/{en,es}.toml -> {en,es}.json
({"key":{"other":"..."}}) — Hugo 0.140 reads it identically (verified with the
pinned hugomods/hugo:exts-0.140.2 image). Enables a 'site' Weblate component.

Update TRANSLATIONS.md: site is now a component (go-i18n-json), not deferred.
2026-07-15 19:42:54 +02:00
7d5f26ff4a feat(links): surface source repo + Weblate links on site and in app
- site: set sourceURL (git.comunes.org/comunes/tane) and weblateURL
  (translate.comunes.org/projects/tane) — activates footer + collaborate links
- app About screen: add 'Source code' and 'Help translate' link tiles
- i18n: add about.sourceCode / about.translate / about.translateSubtitle
  (en base + es/pt/fr/de/ast; ja falls back to base), regenerate slang
- docs: add TRANSLATIONS.md runbook for the Weblate app component + git
  token + slang-regeneration workflow
2026-07-15 19:12:16 +02:00
991785821f feat(screenshots): localize sample variety & market names per shot language 2026-07-15 17:48:44 +02:00
ff7e7e120f docs(web): add deploy runbook for tane.comunes.org 2026-07-15 17:19:48 +02:00
59ee5221de chore(site): regenerate legal pages from docs masters (canonical wrapping) 2026-07-15 15:59:17 +02:00
1ce32c2b5c feat: cover seedlings (plantón) in copy + legal, backup cadence, server picker
Beta-tester feedback triage. The data model already had LotType.seedling as
first class; the gaps were copy and UX.

- Seedlings/plantones: broaden landing hero (EN/ES), in-app legal notice, and
  all legal texts (site + docs masters) from seeds-only to "seeds and
  seedlings", with a live-plant phytosanitary/transport caveat. Seeds stay the
  hero — targeted, not a blanket rename.
- Backups: settings line now states the 7-day cadence explicitly; cadence lives
  in AutoBackupService.backupInterval as the single source for text and schedule.
- Community servers: replace the manual wss:// text box with a checklist of the
  known servers (defaults visible/toggleable) plus an "add server" affordance
  with basic validation. No jargon in the UI.

i18n across en/es/pt/fr/de/ast (ja falls back). Tests updated + a new
server-picker widget test.
2026-07-15 15:57:23 +02:00
7891a973f4 feat(screenshots): CC0/PD example photos for all visible varieties (+CREDITS) 2026-07-15 13:19:24 +02:00
eed96b2a75 feat(screenshots): real maize photo as hero variety, surfaced at top of inventory 2026-07-15 13:07:46 +02:00
6ee61046c8 fix(web): fingerprint screenshot URLs (bust proxy cache) + fix header logo aspect 2026-07-15 12:47:49 +02:00
a7ec13f2f1 fix(web): center unread badge on the menu icon, not the tap target 2026-07-15 12:47:27 +02:00
7f6c88039c fix(web): use red (error color) for unread badge instead of green 2026-07-15 12:45:39 +02:00
bedcc7e398 docs(web): link Plantare to the original plantare.ourproject.org 2026-07-15 12:34:17 +02:00
bb5d09bc6a fix(screenshots): precache asset images so the home logo renders; explain the Plantare name 2026-07-15 12:26:18 +02:00
a3697e6b3e feat(web): SEO/social cards, security headers, PWA icons, FAQ, status, get-involved, captions 2026-07-15 12:10:30 +02:00
a719e9c172 docs(web): add a brief nod to the WAT system on the About page 2026-07-15 08:12:31 +02:00
1b26733b6e docs(web): reframe the name around trust-based printed rice notes (no debt) 2026-07-15 07:56:23 +02:00
9c51f48aa3 docs(web): ground the name in the suiko rice-seed loan, Plantare as its inverse 2026-07-15 07:47:26 +02:00
8f4b14ed45 docs(web): explain the Japanese name + yui reciprocity on About 2026-07-15 07:21:35 +02:00
8dce6f7027 feat(web): tane.comunes.org landing + localized app screenshots
- Hugo site (site/): EN/ES intro + legal (generated from docs/legal), an
  ES/EN About page from docs/{que-es-tane,what-is-tane}.md, seed-green theme,
  responsive header, store-badge placeholders, multi-stage Hugo->nginx image.
- Golden screenshot harness (test/screenshots/): en,es,fr,de,pt,ja + RTL demo,
  real fonts via DejaVu Sans + FontManifest; skip-by-default tag so CI stays
  green. collect_screenshots.sh feeds site/ and fastlane phoneScreenshots.
- Drop editorial notes from the public explainer.
2026-07-15 02:21:42 +02:00
bbf2e97027 docs(claude): record the widget-test hang gotcha + OS timeout wrapper 2026-07-15 01:28:20 +02:00
7a82505a4e feat(plantare): tie the propose form to a real seed
The propose sheet used a free-text seed name, unlinked from the
inventory. Now the seed is picked from your catalogued varieties so the
Plantaré is always tied to a real Variety (tap-through to its detail, and
it shows in that seed's commitments):

- Seed field is an Autocomplete over the inventory; on send the typed name
  resolves to the matching Variety, or creates a quick one if it's new —
  so varietyId is never null. Sheet takes the VarietyRepository; chat
  passes it.
- New repo one-shot `varietyLabels()` (id + label, no joins) feeds the
  picker. Deliberately a Future, not `watchInventory()` — a transient
  sheet must not hold a live Drift subscription (that hung the widget test
  ~36 min). Tests use it too and now run in ~2s with bounded pumps + a
  tall surface, no pumpAndSettle.

Tests: a new name creates & links a Variety; a matching name links the
existing one without duplicating. ui/services/data plantare suites green.
2026-07-15 01:24:50 +02:00
4ab146b157 docs(plantare): mark bilateral signed record shipped
Flip plantare-bilateral.md from "design, not yet built" to "v1 shipped",
summarize what landed (transport / schema v12 / service / UI), resolve
the open questions inline with the decisions made, and list the honest
follow-ups (durable outbox, accept-after-restart, rating anchor,
provenance DAG, paper/group/forgiveness sync).
2026-07-14 11:23:09 +02:00
e78656bc07 feat(plantare): UI — propose from chat, review & sign on the ledger
The viral loop, made usable end-to-end:

- Propose sheet (plantare_propose_sheet.dart): from a chat with a peer
  (their key already in hand), pick your side, name the seed, choose what
  comes back (similar · non-GMO organic / work hours / other) and an
  optional return-by, then sign and send. Reached from the chat overflow
  menu; confirms "waiting for them to sign".
- Plantares screen: incoming proposals show Accept & sign / Decline right
  on the tile; every bilateral row wears a handshake badge — awaiting
  signature, signed by both, or declined. Accept falls back to a gentle
  "offline" nudge if the proposal isn't in hand yet.
- i18n: full en + es for the bilateral flow; other locales fall back to
  base per slang config.

Wire-up only touches human copy (no jargon) and stays behind the
optional PlantareService, so inventory-only builds are unaffected.

Tests: propose sheet drives a real sign+send; the ledger renders the
signed/awaiting badges. Fake SocialSession in your_people test gains the
new transport getter. Widget tests targeted + timed. All green.
2026-07-14 11:23:09 +02:00
b607ddde41 feat(plantare): PlantareService — orchestrate the signed handshake
The app-layer driver that turns local intent into a signed proposal,
counter-signs or declines incoming ones, and reconciles every move into
the local ledger. Cryptography and wire format stay in commons_core;
this owns persistence and orchestration.

- propose(): builds + self-signs a PlantarePledge, records the local row
  (remoteState=proposed, my stub) and sends it. Direction maps to
  debtor/creditor: iReturn = I received and owe, owedToMe = I gave.
- accept(): counter-signs the exact in-hand proposal (verified) and sends
  the doubly-signed copy back, closing the row.
- decline(): notifies the proposer and marks the row declined.
- ingest(): verifies stubs before storing — a bad-signature proposal or a
  half-signed "accept" is dropped; proposals not addressed to me are
  ignored. Pending proposals held in memory keyed by pledge id (relay
  redelivers on reconnect), so accept signs the verified payload.

Wired into DI + Bootstrap alongside the inbox/sync listeners and torn
down/rebuilt on identity switch. SocialSession now exposes the transport.

Tests: full propose→accept close, decline, and the three drop paths with
a records-only transport + real repos. services/data green.
2026-07-14 11:21:46 +02:00
01fba40ec2 feat(plantare): schema v12 — bilateral signed columns + repo
Adds the deferred bilateral columns to Plantares (plantare-bilateral.md
§"Schema delta"), all nullable/defaulted so v1 local rows coexist
untouched:

- pledgeId (the shared id both parties key their row by), debtorKey /
  creditorKey, debtorSignature / creditorSignature, movementId (the
  shared hand-over Movement for the provenance DAG), remoteState
  (proposed/accepted/declined — the handshake, distinct from status),
  returnKind (similar/workHours/other, default similar) + workHours.

Repo: createPlantare grows optional bilateral params; plantareByPledgeId
looks a row up by the shared id; applyPlantareSignatures counter-stamps
an incoming accept; setPlantareRemoteState records a decline. The
JSON codec carries every new field so they ride backups.

Versioned migration is guarded/idempotent like the others; schema v12
dumped, test helper regenerated, migration test covers v1..v11 → v12.
db + data + services 295/295 green.
2026-07-14 11:21:46 +02:00
3f622f7bf7 feat(plantare): PlantareTransport foundation in commons_core
The bilateral signed Plantaré's transport layer — the "formulario
bilateral firmado" from plantare-bilateral.md — as a new interface
alongside the other *Transport contracts, on the shared NostrConnection.

- PlantarePledge: the canonical, byte-stable core (debtor/creditor keys,
  seed label, return kind, dates) plus the two Schnorr stubs. Any edit
  changes the signing hash, so an accept is always over an immutable
  payload.
- PlantareCrypto: BIP-340 signing/verification over SHA-256 of the core,
  reusing the same primitive Nostr uses for events — a pubkey both
  identifies a party and verifies their stub.
- PlantareTransport + NostrPlantareTransport: propose → accept →
  counter-sign (and decline), private end-to-end. Rides the existing
  NIP-17 gift wrap carrying a tagged JSON payload, so the relay sees only
  ciphertext and an ephemeral author. Offline QR/NFC is the same payload
  without a relay.
- Message transport skips Plantaré payloads on the shared kind-1059
  channel (and vice-versa), so moves never surface as chat.

Tests: pure pledge/crypto + full handshake over a hermetic relay,
including no-leak and no-chat-bleed. commons_core 101/101 green.
2026-07-14 11:21:46 +02:00