Commit graph

66 commits

Author SHA1 Message Date
e4c62f2b56 fix(fdroid): cap Gradle heap + drop daemons so the build survives host RAM pressure
All checks were successful
ci / test-commons-core (push) Successful in 54s
ci / analyze (push) Successful in 1m51s
site / deploy (push) Successful in 40s
ci / test-app-seeds (push) Successful in 9m28s
The reproducible build OOM-killed the Gradle daemon ('daemon disappeared
unexpectedly') mid flutter-build-apk on the shared runner. The app's
gradle.properties reserves -Xmx8G+4G metaspace (~12G), and the fdroid
build also compiles tesseract4android from source first (its daemon
lingers), so combined peak RAM trips the OS OOM-killer under contention
(the same build succeeded on a quieter host earlier). Scope the fix to
the fdroid build (don't touch the committed 8G the play/local builds
rely on): run tesseract's gradle with --no-daemon so it frees memory
before the app build, and append a lower -Xmx4g + org.gradle.daemon=false
override to gradle.properties in prebuild (last-key-wins; F-Droid runs
the same steps and memory settings don't change output bytes, so it stays
reproducible).
2026-07-21 17:43:37 +02:00
08459ad29d fix(fdroid): strip flutter_tesseract_ocr's stale jcenter buildscript
All checks were successful
ci / test-commons-core (push) Successful in 45s
ci / analyze (push) Successful in 1m30s
site / deploy (push) Successful in 34s
ci / test-app-seeds (push) Successful in 8m8s
The plugin's android/build.gradle pins its own AGP 7.1.2 and resolves it
via jcenter() (dead since 2021). On a cold Gradle cache the AGP-7.1.2
transitives (apkzlib -> fastutil/json-simple/javawriter) only resolve
from jcenter and fail hard, breaking the reproducible fdroid build.
Warm-cache runs masked it (the one green armeabi-v7a run never hit
jcenter). Strip that buildscript block in prebuild so the plugin
inherits the app's AGP 8.11.1 (settings.gradle.kts) and never touches
jcenter or old AGP at all.
2026-07-21 16:50:11 +02:00
fa768ef17f feat(site): add Portuguese to the landing site
All checks were successful
ci / analyze (push) Successful in 2m43s
ci / test-commons-core (push) Successful in 1m32s
site / deploy (push) Successful in 1m23s
ci / test-app-seeds (push) Successful in 12m26s
Mirror the es/ pattern: docs/legal/pt/ + docs/o-que-e-tane.md as the
Portuguese source of truth, build-legal.sh extended to generate the
Hugo pt.* pages from them, config.toml gets a [languages.pt] entry,
i18n/pt.json translates the UI chrome. og-pt.png is a placeholder copy
of og-en.png until a proper Portuguese social card is made by hand
(same as the other og-*.png, per DEPLOY.md). Verified locally with the
Docker build: /pt/, /pt/about/, all four /pt/legal/ pages and the
lang-switch link all resolve correctly.
2026-07-20 23:35:26 +02:00
071be44851 perf(android): R8, bitmap downscaling, edge-to-edge; recover device compat; publish to production
Some checks are pending
ci / analyze (push) Waiting to run
ci / test-commons-core (push) Waiting to run
ci / test-app-seeds (push) Waiting to run
site / deploy (push) Successful in 1m8s
Device compatibility (regression fix):
- The CAMERA permission (from zxing_barcode_scanner / image_picker) implicitly
  required android.hardware.camera, excluding camera-less devices — Play showed
  Automotive -96%, Chromebook -86%, TV -25%. Declare camera & location
  uses-feature required="false" to keep those devices supported.
- Detect a real camera at runtime (PackageManager.FEATURE_CAMERA_ANY via the
  existing MethodChannel), cache it at bootstrap, and hide the QR scan button and
  the camera photo-source option when absent, so no broken actions are offered.

Play "app optimization" recommendations:
- Enable R8 (isMinifyEnabled + isShrinkResources) with keep rules for the
  OCR (tesseract4android), SQLCipher and notifications JNI/reflection code.
- Bitmap downscaling: cacheWidth/cacheHeight (and ResizeImage for avatars) on
  list thumbnails and avatars so photos decode to on-screen size, not full res.
- Edge-to-edge: opt in with transparent system bars in main().

Release flow:
- Tagged builds now publish to the production track at 100% (was internal);
  add a manual deploy_internal lane as a QA safety net.
- Document country/region availability as a Play Console setting (not in-repo).
2026-07-20 22:53:48 +02:00
06e2ad29c9 chore(release): v0.1.9 (+11) — single-run reproducible developer-signed (SOURCE_DATE_EPOCH comes from the app commit, not fdroiddata)
Some checks failed
ci / test-commons-core (push) Successful in 43s
ci / analyze (push) Successful in 1m24s
site / deploy (push) Successful in 28s
ci / test-app-seeds (push) Successful in 9m35s
release / fdroid_reference (push) Failing after 21s
release / play (push) Successful in 18m50s
2026-07-20 17:24:28 +02:00
bec3493e37 Revert "ci(release): revert to F-Droid-signed recipe; drop pre-merge reference build"
This reverts commit 4d99e1a840.
2026-07-20 17:13:46 +02:00
e054e280dc Revert "docs(fdroid): post-merge runbook for reproducible developer-signed builds"
This reverts commit 85a75ac3b7.
2026-07-20 17:13:46 +02:00
85a75ac3b7 docs(fdroid): post-merge runbook for reproducible developer-signed builds
All checks were successful
ci / test-commons-core (push) Successful in 51s
ci / analyze (push) Successful in 1m35s
site / deploy (push) Successful in 34s
ci / test-app-seeds (push) Successful in 6m40s
2026-07-19 11:36:15 +02:00
4d99e1a840 ci(release): revert to F-Droid-signed recipe; drop pre-merge reference build
All checks were successful
ci / test-commons-core (push) Successful in 44s
ci / analyze (push) Successful in 1m26s
site / deploy (push) Successful in 30s
ci / test-app-seeds (push) Successful in 6m8s
2026-07-19 11:19:46 +02:00
50edb5ff75 ci(release): vendor fdroid config+srclibs in-repo (no gitlab clone); v0.1.8 (+10)
Some checks failed
ci / test-commons-core (push) Successful in 59s
ci / analyze (push) Successful in 1m53s
site / deploy (push) Successful in 33s
ci / test-app-seeds (push) Successful in 9m52s
release / fdroid_reference (push) Failing after 13s
release / play (push) Successful in 19m22s
2026-07-19 09:54:31 +02:00
9b0ef1fc40 chore(release): v0.1.7 (+9) — reference APKs via fdroid buildserver
Some checks failed
ci / test-commons-core (push) Successful in 44s
ci / analyze (push) Successful in 1m27s
site / deploy (push) Successful in 29s
ci / test-app-seeds (push) Successful in 8m51s
release / fdroid_reference (push) Failing after 1m32s
release / play (push) Successful in 17m48s
2026-07-19 09:32:39 +02:00
b906161d70 ci(release): produce F-Droid reference APKs via fdroid build in buildserver image, then sign 2026-07-19 08:56:54 +02:00
b76083be57 chore(release): v0.1.3 (+5) — reproducible developer-signed F-Droid
All checks were successful
ci / test-commons-core (push) Successful in 1m0s
ci / analyze (push) Successful in 1m55s
site / deploy (push) Successful in 34s
ci / test-app-seeds (push) Successful in 11m39s
release / android (push) Successful in 24m33s
2026-07-19 00:03:53 +02:00
f1aa8f8e66 feat(app): scan a printed seed label back into its record
Closes the physical↔digital loop the labels opened: the QR on a printed
envelope (tane://seed, already encoded by seed_label_codec) can now be
scanned from the inventory bar. A known label opens its variety; an
unknown one asks before adding anything, then creates the variety (species
linked by exact scientific name when bundled) with a lot carrying the
label's year and origin. Scanner is pure ZXing (zxing_barcode_scanner,
MIT) — no ML Kit, no Play Services, F-Droid-safe, the stack Ğ1nkgo ships.
Mobile-only; other platforms don't show the button (OCR precedent).
The post-scan flow is a plain function (handleScannedPayload) so it's
widget-tested without a camera.
2026-07-18 12:26:27 +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
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
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
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
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
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
5b64fe14b3 docs: de-link spike findings from spike/ code (moved to private repo) 2026-07-15 20:27:45 +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
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
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
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
7ae6becd8f feat(i18n): full RTL/CJK support — fonts, Japanese locale, directional fixes
Bundle Noto Sans Arabic + Noto Sans JP (SIL OFL 1.1) as per-glyph fallbacks
for both the UI text theme and every generated PDF, so RTL (Arabic) and CJK
render on all platforms — including desktop, where the system font may lack
them — instead of tofu. A shared pdf_fonts.dart centralizes the PDF theme and
the three label/catalog/recovery services reuse it.

Add Japanese (ja) as the CJK reference locale — fittingly, the app's own name
is Japanese (種, tane, 'seed'). Core strings translated; the rest fall back to
English via slang. Wired into supportedLocales (automatic) and the settings
picker.

Fix three physical Alignment.centerLeft -> AlignmentDirectional.centerStart in
variety_detail_screen, and make month-abbreviation and avatar-initial
truncation grapheme-safe (.characters) so CJK text is never cut mid-character.

Tests: CJK/Arabic PDF glyph render, ja locale resolution + English fallback.
The chat-bubble mirroring flagged by the audit was verified correct (already
respects Directionality) and left unchanged.
2026-07-14 11:11:19 +02:00
adf396d49d feat(plantare): surface product link + dates; spec the bilateral record
The Plantaré screen stored madeOn/dueBy/varietyId but showed none of them,
so it felt half-built. Surface what's already there (no schema change):

- watchPlantareViews() joins each commitment with its variety label
- tile shows the made-on date, a "Return by {date}" line (amber + "overdue"
  when an open promise is past due, via new seedWarning colour), the variety
  name, and taps through to /variety/:id
- add sheet gains an optional return-by date picker (createPlantare already
  took dueBy)
- variety detail shows a read-only commitments section (hidden when empty,
  no add button — honours the single hand-over door)
- i18n en/es/pt/ast; tests for the join, dueBy round-trip, tile, and section

Also specs the deferred two-sided record in docs/design/plantare-bilateral.md
(Nostr pubkey counterparty, PlantareTransport propose->accept->counter-sign,
deferred key/signature/movement columns, provenance DAG, reputation anchor),
with a faithful transcription of the paper Plantaré v0.4 (BAH-Semillero 2009,
CC-BY-SA). Cross-linked from data-model §2.7 and sharing-model §6.
2026-07-13 18:06:33 +02:00
447590862e docs(release): point the store checklist at the legal/Play-compliance docs 2026-07-13 08:26:38 +02:00
3229b2c24d docs(legal): full legal package — privacy, terms, community rules, seed-law notice (en+es) + Play/Apple/analysis internal docs 2026-07-13 08:24:27 +02:00
51e6bf019d docs(store): rename Tanemaki → Tane in Play Store metadata and mockups
Fastlane title.txt + full_description.txt (en-US, es-ES) now lead with
Tane and keep tanemaki (種まき) as etymology; CI comment and the Material
mockups updated too.
2026-07-12 13:16:53 +02:00
6fba203f2e docs: finish Tanemaki → Tane rename (user-facing docs + origin doc)
Make Tane primary in README, VISION, CLAUDE, the intros and the
plain-language explainer (renamed que-es-tanemaki.md → que-es-tane.md,
dropping its "provisional name" caveats); keep Tanemaki (種まき) only as
the etymology.

PLAN.md is the origin record: its naming section §5-ter is preserved
verbatim as history under a dated "superseded" note, and the Nota de
vigencia now records Tane + the tane.comunes.org domain.
2026-07-12 13:13:56 +02:00
1e2c66a982 docs: rename Tanemaki → Tane in design docs and notes
Product-name mentions → Tane; backup-file extension .tanemaki → .tane;
website tanemaki.app → tane.comunes.org. Etymology-bearing docs
(README, VISION, PLAN, CLAUDE, intros) handled separately.
2026-07-12 13:09:12 +02:00
74c7edaecd docs: plain-language 'what is Tanemaki' explainer (es)
A short, all-audiences write-up derived from VISION.md: names concepts
like free software / copyleft / decentralised and explains each in plain
words rather than assuming them. States the name is tentative.
2026-07-11 22:21:52 +02:00
ee2fdc1e93 docs(trust): record the ego-centric pivot and ratings v1
network-trust.md §2 rewritten (ego-centric model, misuse resistance,
honest losses, unburnt Duniter bridge) + new §2.1 for ratings.
open-decisions.md: 2026-07-10 WoT-parameters decision superseded;
two new dated entries (ego-centric trust, ratings v1 with its soft
conversation anchor and the strong-anchor question kept open).
CLAUDE.md Block 2 paragraph updated to match.
2026-07-11 13:17:32 +02:00
6cff0d0b11 feat(chat): usable 1:1 chat — bottom-anchored, Drift-backed, dated
- Anchor the message list to the bottom (`reverse: true`) so new messages
  stay in view instead of landing below the fold.
- Move chat history from the OS keystore (O(n²) JSON blob, silent 200-msg
  cap) to a separate encrypted Drift/SQLCipher DB (`ChatDatabase`):
  indexed append, uncapped history, dedup as a unique-key invariant. It's
  an ephemeral per-device cache, isolated from the inventory schema, its
  migrations, and its sync. No data migration (pre-release).
- Add day separators (Today/Yesterday/locale date) and a per-bubble time,
  all via ICU (12/24h per locale; Localizations locale maps Asturian →
  Spanish for intl date symbols).
- Add peer avatars (deterministic colour from the pubkey + name initial),
  surface send failures that were previously silent, and make bubble text
  selectable (addresses, links).
- New i18n keys in en/es/pt/ast; tests for grouping, formatting, avatars,
  scroll anchoring, storage and send errors.

Docs: docs/design/chat-storage.md + open-decisions.md.
2026-07-11 06:40:50 +02:00
182c334883 feat(sync): encrypted device-to-device sync transport (core foundation)
The most foundational Block-2+ gap: the data model was built CRDT-ready
(HLC, tombstones, LWW, append-only Movement) and the import reconciler
proves the merge — but nothing replicated a device's inventory to your
OTHER devices. Only manual file backup/restore moved data between devices.

This lands the transport foundation in commons_core (seed-agnostic, on the
shared connection — the 'one connection, N interfaces' shape):

- SyncTransport: moves an opaque, encrypted snapshot blob between ONE
  identity's own devices. The core carries bytes + does the crypto; the app
  decides what the bytes are and how to merge them.
- NostrSyncTransport: NIP-78 app-data (kind 30078, addressable/replaceable
  per device via the d-tag), content NIP-44-encrypted TO SELF, discovery
  filtered to your own author key. Each device keeps one replaceable record.

Tests (MiniRelay, pure Dart): a snapshot replicates to the identity's other
device; the relay only ever sees ciphertext; another identity neither
receives nor could decrypt; re-push replaces; two devices keep their own.

Confirms the open-decisions §D.4 guarantee (sync leaks neither the key nor
plaintext). NEXT slice (app): a SyncService that serializes the inventory
(reusing ExportImportService), pushes on mutation, and runs the existing
idempotent importInventory on receive; a stable per-install device id;
wire sync into SocialSession.
2026-07-10 23:16:07 +02:00
4cf53f259f feat(trust): full Duniter web-of-trust membership (params + referents)
Slice 4 of Block 2. The pure rule was already parameterised; this adds the
policy, cold-start and UI around it.

- commons_core: WotParams (sigQty/stepMax/sigValidity, Duniter defaults) +
  WebOfTrust.membersWith; npubToHex helper (NIP-19 decode) for adding roots.
- WotSettings (keystore): the active parameters, configurable — a young
  network loosens them and tightens as it grows, as Ğ1 did. Defaults Duniter.
- TrustReferents: the bootstrap 'seeds' membership is measured from — a
  bundled asset (empty until real founders are curated, no invented keys)
  unioned with referents the user adds by npub/QR. Honest cold-start.
- TrustCubit: computes the full membership verdict against referents+params
  alongside the personal circle, and exposes a TrustTier (networkMember >
  inYourCircle > vouched > unknown). Certifications issued with the active
  validity (they expire and renew, Duniter rule).
- UI: chat trust badge by tier; a 'Network of trust' screen (manage roots +
  advanced params) reached from the profile. i18n en/es/pt/ast.

Tests: WotParams/membersWith, npubToHex, TrustReferents, WotSettings, and
TrustCubit tiers/membership. Resolves the WoT-parameters decision
(open-decisions §B). Trust net stays empty/undetermined until seeded — by
design; users bootstrap their own roots.
2026-07-10 21:02:08 +02:00
993f7b37ab feat(identity): switch social identity, all from the one backup
Adds pseudonymous, switchable social identities derived from the SAME root
seed via an account index (NostrKeyDerivation.deriveFromSeed(seed, account)).
HKDF is one-way so accounts are unlinkable to the Ğ1 key; account 0 is the
original identity, byte-for-byte unchanged (no rotation for current users),
and every account regenerates from the single seed — so switching adds
nothing to back up.

- SocialAccountStore: keystore-backed active account + max created.
- Per-identity stores (chats, profile, name cache) namespaced by account
  scope (account 0 = legacy keys, no migration) so identities never mix.
- switchSocialAccount() re-derives the identity, re-scopes the stores and
  restarts the inbox listener; RestartWidget rebuilds the tree to pick up
  the new social singletons. DB/inventory untouched.
- Profile 'Your identities' switcher: list, create, switch (with a note
  that messages/contacts are kept separate per identity). i18n en/es/pt/ast.

Tests: account-indexed derivation (legacy 0 unchanged, accounts distinct
yet deterministic, negatives rejected); SocialAccountStore; per-identity
store scope isolation. Resolves the flagged 'change identity' decision
(open-decisions §B).

Known: switching resets navigation to home (full tree rebuild).
2026-07-10 20:22:24 +02:00
5741d6bde8 docs(block2): note 'change social identity' as an important pending decision
User-flagged (on-device feedback): no way to change the social identity today
(derived once from the root seed at startup). Records the two options —
pseudonymous social key (recommended) vs full root-seed reset — and the runtime
re-derivation implications, for a future round.
2026-07-10 13:41:44 +02:00
a03154030b docs(block2): lift the gate — open the social round
The de-risking spike validated the whole social happy path, so Block 2 moves
from "do NOT start" to STARTED. Records the build order (transport foundation in
commons_core first, on the vetted pure-Dart nostr lib) and marks open-decisions
D.3/D.7 as resolved by the spike.
2026-07-10 02:26:16 +02:00
d433748ab5 spike(block2): de-risk web of trust — the last big unknown
Adds TrustTransport as the third interface on the shared NostrConnection,
completing the social-layer happy path in the spike:

- WebOfTrust: pure, Flutter-free Duniter membership rule (N certs from members +
  within distance D of bootstrap referents), iterated to a fixpoint. The
  commons_core-worthy piece; TDD'd (threshold, distance cutoff, transitive
  growth, expired/revoked/self exclusion).
- NostrTrustTransport: certifications as a custom addressable kind (30777,
  keyed by issuer+subject) — certify renews, revoke replaces, certs expire.
- Trust filters spam (network-trust §2): seeds certify Alice; Eve stays
  uncertified; Bob discovers both offers and annotates authors — Alice known,
  Eve unknown — all over ONE shared connection.

Findings updated: WoT risk High -> Medium (policy/bootstrap, not feasibility);
overall scope Medium-High -> Medium — all three transport contracts now proven.
30 tests green, analyzer clean, Block 1 untouched.
2026-07-10 02:17:35 +02:00
8a81aaf442 spike(block2): de-risk NIP-17 messaging + validate shared-connection shape
Extends the Block 2 spike to attack the highest-risk unbuilt piece (private
messaging) and to prove the Q2 architecture recommendation with running code:

- NostrConnection: one shared socket+key+sign+REQ/EOSE lifecycle. Refactored
  NostrOfferTransport onto it; added NostrMessageTransport — two thin contracts
  on ONE connection (the 'one connection, three interfaces' shape).
- NIP-44 v2 encryption (secp256k1 ECDH -> ChaCha20 + HMAC, length-hiding pad).
- NIP-17/NIP-59 gift-wrap: rumor(14) -> seal(13) -> wrap(1059, ephemeral key).
  Alice->Bob DM round-trips through the relay: encrypted, sender authenticated,
  and metadata-private (relay/eavesdropper sees only ciphertext, an ephemeral
  author and the recipient p-tag — Alice stays hidden).

Findings updated: NIP-17 risk drops Medium-High -> Medium (hardening, not
feasibility); next de-risking target is the web of trust. NIP-44 not yet
vector-verified (noted). 20 tests green, analyzer clean, Block 1 untouched.
2026-07-10 02:11:54 +02:00
32ddaf1714 spike(block2): de-risk social layer — key derivation, OfferTransport, NIP-99 round-trip
Throwaway research spike (spike/ branch, outside pub workspace, no prod deps
touched). Validates the open Block 2 decisions before committing a funded round:

1. Deterministic one-way secp256k1 (Nostr) key derived from the Ğ1 root seed
   via HKDF — user still backs up ONE thing. Reproducible + signs (BIP340).
2. OfferTransport abstraction over Nostr NIP-99 (kind 30402); Offer stays
   inventory/location-agnostic, geohash coarsened on the wire (tested).
3. publish->discover-by-geohash proven end-to-end against an in-process
   hermetic mini-relay (~34ms round-trip).

Findings + risks + recommendation in docs/design/spike-block2-findings.md.
Block 1 suite untouched. 14 tests green, analyzer clean.
2026-07-10 01:57:25 +02:00
4acf227e30 chore(release): beta packaging — signing, changelog, store metadata, scale test
- Android release signing reads a gitignored key.properties, falling back
  to debug keys so contributors can still build --release.
- CHANGELOG.md (human, newest-first) + Fastlane/F-Droid metadata (en/es)
  with descriptions derived from docs/intro.md.
- docs/release.md: the by-hand build + manual smoke checklist (no CI yet).
- inventory_scale_test guards the list query against N+1 at 3000 varieties.
2026-07-09 23:10:01 +02:00