diff --git a/@hardware/docs/IDEAS.md b/@hardware/docs/IDEAS.md index d12b996..cfe39ba 100644 --- a/@hardware/docs/IDEAS.md +++ b/@hardware/docs/IDEAS.md @@ -58,6 +58,136 @@ Edge / back view: optional pogo pads for factory recovery only ``` +### Component layout — does it all fit, does it balance? + +Card footprint: standard ID-1 / credit-card, **85.6 × 54 mm**, target +**3–4 mm thick**. Budget every external surface (front, back, edge) +plus an internal Z-stack of ~5 layers. Heavy / area-hungry components +get **stacked in Z** rather than fighting for X-Y real estate. + +**Front face** (member-facing, calculator UX): + +``` + ┌──────────────────────────────────────────────────────┐ + │ ◉ cocotte ▒ status LED │ ← top status row + │ ┌────────────────────────────────────────────────┐ │ + │ │ e-ink display (~50 × 25 mm) │ │ ← display + │ │ balance · peer handle · amount · code │ │ + │ └────────────────────────────────────────────────┘ │ + │ │ + │ ┌───┐ ┌───┐ ┌───┐ ┌─────┐ │ + │ │ 7 │ │ 8 │ │ 9 │ │ ÷ │ │ + │ ├───┤ ├───┤ ├───┤ ├─────┤ │ ← 3×4 numeric + + │ │ 4 │ │ 5 │ │ 6 │ │ × │ │ 1×4 operator + │ ├───┤ ├───┤ ├───┤ ├─────┤ │ membrane keypad + │ │ 1 │ │ 2 │ │ 3 │ │ − │ │ + │ ├───┤ ├───┤ ├───┤ ├─────┤ │ + │ │ . │ │ 0 │ │ ⌫ │ │ + │ │ + │ └───┘ └───┘ └───┘ └─────┘ │ + │ │ + │ [ MENU ] [ ◉ SEND ] [ = / CONFIRM ] │ ← action row + └──────────────────────────────────────────────────────┘ +``` + +Front is the most pixel-budget-constrained surface. Membrane keypad +sits directly on the main PCB; e-ink display is laminated above. No +free area on the front to spare for the LED strip or piezo — those +move to edge / back. + +**Back face** (the radio + power face — everything stacks here): + +``` + ┌──────────────────────────────────────────────────────┐ + │ serial · cocotte ······························· │ + │ ┌─────────────────────────────────────────────┐ │ + │ │ │ │ + │ │ NFC antenna loop ── outer ring │ │ ← NFC + Qi coils + │ │ ┌─────────────────────────────────────┐ │ │ stacked + │ │ │ │ │ │ (flex multilayer, + │ │ │ Qi v2.1 receiver coil │ │ │ same X-Y zone) + │ │ │ ( ~38 × 38 mm spiral ) │ │ │ + │ │ │ │ │ │ + │ │ └─────────────────────────────────────┘ │ │ + │ │ │ │ + │ │ NFC tap zone (this whole region) │ │ + │ └─────────────────────────────────────────────┘ │ + │ │ + │ ▣ recovery QR (etched, flush) ◡ pogo indent │ ← smooth shallow + │ (4–6 pads) │ indent, flush pogo + └──────────────────────────────────────────────────────┘ +``` + +The Qi coil (~38 mm class) and the NFC antenna loop share the same +X-Y real estate because they're on **different flex layers** and run +at totally different frequencies (Qi ~100 kHz, NFC 13.56 MHz). Stack +order is engineered so neither blocks the other; this is the standard +trick on every card-form wallet that ships Qi today. + +**Edge** (switch + status): + +``` + top edge : ───── perimeter LED strip wraps all 4 sides ───── + left edge : ◀── [ LOCK · SEND · RECV ] ──▶ ◉ piezo port + ░░░ (toggle pulse LED under detent) + right edge : status LED · cellular antenna feed point + bottom edge: (clean — no exposed metal, no port) +``` + +Charging is wireless (Qi), so the bottom edge has no port and stays +clean. Cellular antenna is a meandered trace along the inner side of +the card edge — antenna real estate is what makes the perimeter +ring useful for two things at once (radio + LEDs). + +**Internal Z-stack** (top of card → back of card, ~3–4 mm total): + +``` + ┌──────────────────────────────────────────┐ ← 0.3 mm — front shell + 1 │ front shell + membrane keypad overlay │ + ├──────────────────────────────────────────┤ + 2 │ e-ink display module │ ← 0.5 mm + ├──────────────────────────────────────────┤ + 3 │ main PCB — MCU · modem · secure │ ← 0.6 mm + │ element (EAL6+) · iSIM/eSIM · BLE/NFC │ PCB + components + │ controller · PMIC · piezo step-up · LED │ + │ drivers · supercap (SMD) │ + ├──────────────────────────────────────────┤ + 4 │ Li-Po pouch (~40 × 45 × 1.0 mm, │ ← 1.0 mm + │ ~150 mAh, centered) │ + ├──────────────────────────────────────────┤ + 5 │ multilayer flex — Qi coil + NFC loop │ ← 0.4 mm + │ + perimeter LED strip + piezo flex tail │ + ├──────────────────────────────────────────┤ + 6 │ back shell w/ pogo indent + QR window │ ← 0.3 mm + └──────────────────────────────────────────┘ + ≈ 3.1 mm ── fits the 3–4 mm budget +``` + +**Balance / centre-of-mass check:** +- Heaviest single component is the **Li-Po pouch** (~3–4 g). Placed + centred so the card's CoM stays near geometric centre. +- Display is heavy-ish but mounted at the top half of the front; + battery sits in the lower half of layer 4 to **counterweight**. +- Main PCB components (MCU + modem + secure element) are the densest + silicon area — distribute around the edges of layer 3 rather than + clustering, both for thermal and balance reasons. +- Piezo, the supercap, and the LED drivers go to the *corners* of + layer 3 — naturally balancing each other off-axis. +- Perimeter LED strip + cellular antenna ring the whole card → mass + is symmetric by construction. + +**Does it all fit? Yes, with two tight spots:** +- **Qi coil vs. NFC antenna** share X-Y but live on different flex + layers — solved (already shipping pattern). The risk is yield. +- **Front-face real estate**: keypad + display + action row + status + row is exactly the front, with **zero margin** for adding more UI. + Any future feature that needs front-face pixels (touch, fingerprint + reader) means dropping a key or shrinking the display. Treat the + front as **fully booked**. + +Anything else added later — fingerprint sensor, second display, +solar trickle cells, larger speaker — has to come out of layer 3 +(displace silicon) or grow the Z budget past 4 mm. + ### Function - **Retrieval surface for E2EE + crypto.** Holds the keys / recovery material needed to decrypt member content and authorize crypto operations. Framed @@ -209,9 +339,24 @@ start, both confirm, no roles. - SIM/radio provider strategy (MVNO vs. satellite IoT vs. LoRa-style mesh)? - Relationship to existing standards (Ledger/Trezor seed compat? FIDO2? custom?). -- Session channel *after* the NFC introduction — BLE for nearby peers, - in-band over the radio mesh for distant peers, or both? (Pairing - transport itself is decided: NFC.) +- **Session channel *after* the NFC introduction — this is the single + biggest unresolved hardware decision.** Pairing transport itself is + decided (NFC). The session that follows could be: + - **BLE** — natural for nearby peers, off-the-shelf chipsets, also + gives find-my-wallet a free local proximity stage. Costs an extra + antenna + radio + paired-phone UX wrinkle. Does *not* work if + the two members are not physically close (e.g. wallet-to-wallet + remote tipping). + - **In-band cellular, platform-relayed.** Both wallets push the + session through the cocotte platform over their own LTE-M + radios. Works at any distance. Costs platform availability for + every transaction and adds latency (sub-second still, but not + instant). Simpler BOM — no BLE radio at all. Find-my-wallet + loses the BLE proximity stage. + - **Custom sub-GHz peer mesh (LoRa-class).** No platform in the + loop, works peer-to-peer at range, but adds another radio + + antenna + cert burden. + Decision blocks BOM (BLE chipset yes/no) and find-my-wallet design. - **Pogo-pad layout + adapter form factor.** Charging is decided (Qi primary + bundled USB-C→pogo adapter using the same back-pad contacts that also serve factory recovery). The contact area is a @@ -281,14 +426,48 @@ that critique — but worth being explicit about the framing. fine, the hotel pad doesn't. Source: - https://graniteriverlabs.com/en-us/technical-blog/beyond-qi2-wireless-charging -**Power budget — the actual hard problem.** -- A card-thin Li-Po cell is on the order of 100–200 mAh. Cellular LTE-M - transmit bursts pull 100 mA+. The wallet must be **mostly asleep**: - - Radio idle in LOCK (beacon-only or fully off). - - Radio wakes only on toggle change, NFC tap, or scheduled push. - - Display is e-ink so retention is free. - This is a design constraint, not a blocker — IoT cellular trackers - achieve months of life at this duty cycle. +**Power budget — solvable with a 3-tier hybrid stack.** + +The actual hard problem isn't bulk energy, it's the **peak-current +mismatch**: a card-thin Li-Po can hold a few hundred mWh but can't +deliver the 1–3 A spikes that LTE-M / NB-IoT transmit bursts demand +for 1–2 seconds. The IoT industry already solved this for smart meters +and cellular trackers; the same architecture maps directly onto a +membership wallet: + +1. **Bulk energy — ultra-thin Li-Po pouch.** Mass-produced down to + 0.4–1.0 mm. A 1.5–2.0 mm card-style cell delivers ~100–160 mAh at + 3.7 V (Serui, PADRE, Grepow, UFine, Samsung/LG plastic-pouch parts). + Honeywell already ships products with 0.8 mm cells. Chinese supply + chain is mature here. +2. **Pulse buffer — supercapacitor (or Li-SOCl₂ + supercap hybrid).** + Absorbs the 1–3 A LTE-M transmit burst the Li-Po alone can't + deliver. A 220 F hybrid supercap part delivers ~15 A peak. During + sleep the Li-Po trickle-recharges the cap. This is the *de facto* + architecture for cellular IoT in 2026. +3. **Aspirational always-on trickle — betavoltaic ("diamond") + battery.** Betavolt's Ni-63 / diamond unit is **15 × 15 × 5 mm** + today at 100 µW; a 1 W version is announced. Microwatts are + nowhere near LTE-M's needs **directly**, but the betavoltaic's + role is *trickle-recharging the supercap and Li-Po while the + wallet sits in a drawer*. 50-year half-life on the isotope ≈ a + wallet that doesn't go flat if a member loses it in a couch for a + year. Real status: still pre-mass-market, regulatory questions on + consumer radionuclides — treat as **v2 ambition, not v1 BOM**. + +Sources: +- https://www.serui-battery.com/News/xingyezixun/ultra-thin-1-5-2-0mm-3-7v-100mah-card-style-lithium-polymer-batteries.html +- https://www.pdbattery.com/ultra-thin-battery.html +- https://www.grepow.com/blog/ultra-thin-lithium-polymer-battery-for-thinnest-application.html +- https://www.digikey.com/en/articles/use-hybrids-to-bring-the-benefits-of-both-batteries-and-supercapacitors-to-power-iot-designs +- https://hackaday.com/2026/04/28/2026-green-powered-challenge-supercapacitor-enables-high-power-iot/ +- https://newatlas.com/energy/betavolt-diamond-nuclear-battery/ +- https://www.world-nuclear-news.org/articles/nuclear-battery-chinese-firm-aiming-for-mass-mark + +Duty-cycle posture remains required regardless of stack: +- Radio idle in LOCK (beacon-only or fully off). +- Radio wakes only on toggle change, NFC tap, or scheduled push. +- E-ink display retention is free (no draw while showing balance). **Overall feasibility verdict — buildable with 2026 parts.** - No single component requires invention. Every piece ships somewhere. @@ -301,6 +480,121 @@ that critique — but worth being explicit about the framing. than greenfield. ODM relationship + custom firmware + cocottetech brand layer is the shape of the project. +### Find-my-wallet + +The cellular radio that exists for transfers doubles as a built-in +**self-locator** — fundamentally better than AirTag / Tile (which rely +on a crowd-sourced mesh of other people's phones). The wallet phones +home on its own. + +**The trigger is the *platform*, not the phone.** Member says "find my +wallet" from the cocotte app, web view, or even SMS to the platform. +The platform pushes an **OTA command** to the wallet over LTE-M — +exactly the same downlink path used for any other platform-initiated +message. The wallet doesn't have to be near the member's phone, BLE, +or wifi to receive the find request. Critically: this means **a member +who has lost both their wallet *and* their phone can still find the +wallet** — they log in on a friend's device or call the platform. + +Three response stages, escalating with how close the member is: + +1. **Global — cellular self-report (LTE-M / NB-IoT).** On receipt of + the platform OTA find command, the wallet immediately wakes the + modem, posts the nearest cell tower IDs + signal strength back to + the platform, and the member sees a city-level pin in the app / + web. Wallets also self-report on a slow background schedule (e.g. + 1×/hour while in LOCK) so the *last known location* is always + warm — useful when cellular happens to drop at the moment the + member panics. Power impact is bounded by the duty-cycle posture + already designed in (modem otherwise idle). +2. **Local (~10–100 m) — *only if BLE is already on the BOM*.** This + stage is **conditional**, not a given. BLE was originally proposed + as the post-NFC session channel for peer transfers (see the + transfer-session-channel open question). If that decision lands + on BLE, then find-mode gets a free hot/cold proximity stage — the + platform's OTA command flips the wallet into a higher-rate beacon + and a member's phone shows a range bar. **If transfers end up + running over cellular (relayed through the platform) instead of + BLE, this whole stage disappears** and we go directly from stage + 1 (city-block cellular pin) to stage 3 (strobe + beep). The + wallet is loud and bright enough on platform command that the + missing middle stage is acceptable — you walk into the apartment + and follow your ears. +3. **In-hand (~cm) — perimeter LED strobe + loud piezo tone.** Same + OTA escalation. The wallet drives the **full perimeter LED strip** + in a high-contrast strobe (reusing the transfer-state hardware — + see the Light language section) and fires a **simple loud tone + generator** — sub-1 mm piezo bender driving a single fixed audible + frequency (~3–4 kHz, the ear's peak sensitivity). Not a speaker, + not a musical synth, not voice prompts: one tone, intermittent, + loud enough to find the wallet under a couch cushion or inside a + bag. The simplicity is the point — no codec, no DAC, single GPIO + driving the piezo through a step-up, sub-mA at the cap-buffered + peak. + +Escalation is **member-controlled from the platform UI**, not +automatic by RSSI — "show me on a map", "make it beep", "make it +beep and flash" are three buttons that send three different OTA +levels. The wallet has no idea how close the member's phone is; it +just does what the platform last told it to do. + +**The 30-year-old wallet argument for BLE.** + +Re-examining the BLE question on **longevity / degradation** grounds: +imagine the wallet is 30 years old. The piezo bender has died (glue +fatigue, mechanical wear, solder joint failure). The perimeter LED +strip has dimmed past usefulness (phosphor degradation, driver IC +end-of-life). The e-ink display ghosts. Battery is shot — but the +betavoltaic trickle (v2) keeps the radios alive. + +In that future, **only the solid-state radios are reliably alive**: +the cellular modem and (if equipped) BLE. The find sequence +degrades as follows: + +| Stage | Hardware needed | 30-yr survival | +|---|---|---| +| 1. Cellular pin | LTE-M modem + antenna | ✓ likely OK | +| 2. BLE proximity | BLE chipset + antenna | ✓ likely OK | +| 3a. Strobe | LED strip + drivers + power | ✗ failure-prone | +| 3b. Piezo tone | piezo bender + step-up | ✗ failure-prone | + +Without BLE, a 30-year-old wallet with dead transducers gives you a +city-block pin and nothing else — you can't narrow from "in this +house" to "in this drawer". **With BLE, even with all output +hardware dead, the searcher's phone becomes the UI** (sound, +vibration, visual hot/cold meter all run on the phone side). The +wallet just has to emit a silent beacon — which is the same thing a +$5 Tile does, with no transducers at all. + +This reframes the BLE BOM question: BLE is justified **not only by +the transfer-session-channel decision, but independently by +**longevity guarantee****. A wallet that's a membership-grade +artefact (potentially handed down, kept for decades) needs at least +two redundant find paths, and the two that age best are both +radios. + +Verdict shift: **lean toward BLE on the BOM** regardless of the +transfer-session-channel outcome. Even if transfers run +platform-relayed over cellular, BLE earns its place as the +last-mile finder when local output transducers are end-of-life. + +**State + privacy:** +- Find-mode is an **out-of-band command**, not a switch position. The + hardware toggle stays where the member left it (LOCK / SEND / RECV); + find is just an additional behaviour layered on top by the radio + firmware. +- The wallet's location reports are visible **only to the member's + authenticated account** on the platform. The platform never shares + wallet pings with third parties — and per the [[stance]] section, + not with any regulatory or law-enforcement query either. +- A member can **disable cellular self-reporting** in the app (the + wallet then only locates via BLE while the member is within range, + like a dumb Tile). Default is on; member-controlled. +- "Anti-stalker" inversion is a non-problem here: unlike AirTag, this + wallet can't be slipped into someone else's bag to track them — it's + bound to a member account at provisioning and only reports to that + account's owner. + ### Prior art — is anyone already doing this? (2026-05-18) **Short answer:** every *ingredient* ships somewhere; **the exact diff --git a/@platform/codebase/@features/platform-api/src/entities/index.ts b/@platform/codebase/@features/platform-api/src/entities/index.ts index 7512db1..2608e3f 100644 --- a/@platform/codebase/@features/platform-api/src/entities/index.ts +++ b/@platform/codebase/@features/platform-api/src/entities/index.ts @@ -6,6 +6,15 @@ import { EngagementEventEntity } from './engagement-event.entity.js'; import { MailboxEntity } from './mailbox.entity.js'; import { OrgEntity } from './org.entity.js'; import { OrgMemberEntity } from './org-member.entity.js'; +import { PeerCollaborationEntity } from './peer-collaboration.entity.js'; +import { PeerConnectionEntity } from './peer-connection.entity.js'; +import { PeerEndorsementEntity } from './peer-endorsement.entity.js'; +import { PeerGroupEntity } from './peer-group.entity.js'; +import { PeerGroupMemberEntity } from './peer-group-member.entity.js'; +import { PeerGroupMessageEntity } from './peer-group-message.entity.js'; +import { PeerMentorshipEntity } from './peer-mentorship.entity.js'; +import { PeerMessageEntity } from './peer-message.entity.js'; +import { PeerProfileEntity } from './peer-profile.entity.js'; import { PersonaEntity } from './persona.entity.js'; import { UserEntity } from './user.entity.js'; @@ -20,6 +29,15 @@ export const entities = [ AgentActionEntity, EngagementEventEntity, MailboxEntity, + PeerProfileEntity, + PeerConnectionEntity, + PeerMessageEntity, + PeerGroupEntity, + PeerGroupMemberEntity, + PeerGroupMessageEntity, + PeerEndorsementEntity, + PeerCollaborationEntity, + PeerMentorshipEntity, ] as const; export { AgentActionEntity }; @@ -30,6 +48,15 @@ export { EngagementEventEntity }; export { MailboxEntity }; export { OrgEntity }; export { OrgMemberEntity }; +export { PeerCollaborationEntity }; +export { PeerConnectionEntity }; +export { PeerEndorsementEntity }; +export { PeerGroupEntity }; +export { PeerGroupMemberEntity }; +export { PeerGroupMessageEntity }; +export { PeerMentorshipEntity }; +export { PeerMessageEntity }; +export { PeerProfileEntity }; export { PersonaEntity }; export { UserEntity };