You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit fb00284
Browse filesBrowse the repository at this point in the historyBrowse files
feat: tag index / tag count (TigerTag v2.2) on burn, read, Firestore and .ttag; catalogue grid no longer flickers on a favourite toggle
- SDK tigertag ^1.2.0, forced offline in the main process (TIGERTAG_OFFLINE=1)
- Burn: guided encode stamps chip i of n at byte +39 (0x11 single, 0x12/0x22 twin); migrated docs record tag_index / tag_count
- Re-writes keep the chip's own byte +39 with its timestamp (_keepChipIdentity) — a factory twin keeps 0x12/0x22 through weight / colour syncs
- Read: scans store tag_index / tag_count on users/{uid}/inventory/{UID}; twin pairing refuses pairs the byte rules out (single, count mismatch, same rank)
- Spool card: "Chip i of n" row + "twin still missing" banner; RFID tester shows Tag i of n
- .ttag: exported verbatim, validated on import (0-15, dropped on chipless records); contract in docs/TTAG-FIELDS.md + fields editor
- Chip-only fields: duplicates never inherit tag_index / tag_count
- Catalogue grid patches product badges instead of rebuilding every card on a favourite toggle; product card keeps its photo node
- Verified on real chips (TigerPOD, 2 readers)
- Tag index / tag count (TigerTag protocol v2.2, chip byte +39: high nibble = chip i, low nibble = n chips) — `main.js`, `preload.js`, `renderer/inventory.js`, `renderer/rfid_protocol/tigertag/parser.js`, `renderer/rfid_protocol/tigertag/index.js`, `package.json`, `package-lock.json`
5
+
- SDK `tigertag` 1.1.0 → ^1.2.0, forced offline in the main process (`TIGERTAG_OFFLINE=1` — Studio has its own reference-data service; no daily api.tigertag.io check, no cache-folder writes)
6
+
- Burn: guided encode stamps chip i of n (0x11 single, 0x12 / 0x22 twin) via `rfid:burn-one``{ tagCount, tagIndex }`; the migrated docs record `tag_index` / `tag_count`
7
+
- Re-write paths (`rfid:write-now`, `rfid:encode-cloud`) keep the chip's own byte +39 alongside its timestamp (`_keepChipTimestamp` → `_keepChipIdentity`) — a factory twin no longer loses its 0x12/0x22 on a weight or colour sync; a full write without a readable chip falls back to the doc's `tag_index` / `tag_count`
8
+
- Read: every scan stores `tag_index` / `tag_count` on the inventory doc (unpacked from the SDK's `tag_info`); rows carry `tagIndex` / `tagCount`
9
+
- Twin pairing (2-reader scan + `autoLinkTwinsByTimestamp`) refuses pairs the byte rules out — a chip marked single, mismatched counts, or the same rank twice; unknown (0) never blocks, legacy pairing unchanged
10
+
- Spool card: "Chip i of n" row in Details; a "twin still missing — put the other chip on the reader" banner when `tag_count` ≥ 2 and the partner was never scanned; RFID tester shows "Tag i of n"
11
+
-`.ttag`: exported with the record (verbatim doc); import keeps them when 0–15 and drops them on a chipless record or an out-of-range value; listed as on-chip, optional fields in `docs/TTAG-FIELDS.md` + `playground/ttag-fields-editor/index.html`; `TTAG_ON_CHIP_FIELDS` updated
12
+
- Chip-only: `tag_index` / `tag_count` join `CHIP_ONLY_FIELDS`, so a duplicated (chipless) spool never inherits "chip 1 of 2"; rows of chipless docs ignore them
13
+
- Docs: `docs/firestore-schema.md`, MCP data guide, backend `README.md` (inventory tree)
14
+
- Verified on real chips (TigerPOD, 2 readers): factory 0x12 + single 0x11 of the same product → stored 1/2 and 1/1, NOT paired, missing-twin banner on the 1/2; weight write 1000→950→1000 g touched only page 0x17, byte +39 and timestamp unchanged
4
15
5
16
## Changed
17
+
- TigerScale photo is now the V3 hardware render (README, scale card, empty state) — contributed in PR #34; shipped copy trimmed + resized to 512² and palettised (1.38 MB → 78 KB), full-res master archived (committed c933d61) — `assets/img/TigerScale_V3.png`, `assets-src/img/TigerScale_V3.png`, `assets-src/README.md`, `renderer/IoT/tigerscale/index.js`, `README.md`
6
18
7
19
## Fixed
8
-
- Google sign-in failing with a bare "fetch failed" on some machines: the OAuth token exchange now goes through Electron's `net.fetch` (Chromium stack — system proxy, OS certificate store, same DNS as the browser) instead of Node's `fetch`, and the failure log includes the underlying cause — `main.js`
9
-
- Windows: the whole app crawled on some machines (every click, even a window resize, took one to two minutes) — the USB-scale detection enumerated HID devices SYNCHRONOUSLY on the main thread every 5 s (`HID.devices()`), and on slow HID / Bluetooth drivers each call took seconds. It now uses `HID.devicesAsync()` (worker thread) with an in-flight guard, and when a scan takes over 2 s it logs it and slows polling to once a minute. Confirmed by a user log on v2.32.0: the 10 s launch freeze persisted after the TD1S scan was removed — it was this HID enumeration all along (it runs right after the TD1S init) — `main.js`; `CODEMAP-main.md` discovery-probe ranges re-synced
20
+
- Deleting products (bulk "Delete" in Favorites) was always refused with "permission denied" since the tier-gated attachments rule (v2.12.0): the `products` rule read `request.resource.data` in a single `allow write`, which errors on a delete — split into `allow create, update` (attachment cap kept) + `allow delete: if isOwner()` — backend `firestore.rules` (deployed + committed 4aa71b8)
21
+
- Security: `js-yaml` 4.3.1 → 4.3.2 (CVE-2026-84375 / GHSA-2883-xcg3-v3hh, YAML merge-key DoS), transitive via `electron-updater` (parses `latest*.yml`) — `package-lock.json` (already committed in 22b3f3c; internal, not for release note / What's New)
22
+
23
+
- Toggling ★/❤ on a catalogue product no longer flickers the catalogue grid: a render that lands on the same result list patches the cards' product badges instead of rebuilding every card (which re-inserted the photos 2-3× per click and dropped the chunks scrolled into view); the product card keeps its photo node across re-renders — `renderer/inventory.js` (other views still to audit)
Copy file name to clipboardExpand all lines: docs/TTAG-FIELDS.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -74,6 +74,8 @@ The Header block is the same for every type; the rest of the contract (Required
74
74
|`id_tigertag`|`uint32 · ref id_version.json`|**yes**|**Req if chip**|**Req if chip**|**Req if chip**|**Req if chip**|**OVERWRITTEN ON IMPORT**. The chip's tag id (bytes 0-3). It REFERENCES id_version.json, so only the four ids listed there are legal: 0 RFID Empty, 1542820452 TigerTag, 1816240865 TigerTag Init, 3155151767 TigerTag+. Required of a record that HAS a chip; a chipless record (uid TigerData_… or legacy CLOUD_…) has no chip and therefore no version, so it must NOT carry the field at all — it is written for the first time when a real chip is programmed. Studio ≤2.15.0 stored a random u32 here on chipless materials, a value outside the referential; 2.16.0 stopped writing it and deletes the stray ones. Import drops the field (which is what makes the copy not a TigerTag+); Restore keeps it verbatim. |
75
75
|`id_product`|`uint32 (0–4294967295)`|**yes**| Opt | Opt | Opt | Opt |**OVERWRITTEN ON IMPORT**. Catalogue product id — look up a real one in the public catalogue at https://tigersystem.io/fr/catalog. When unknown it MUST be `4294967295` (`0xFFFFFFFF`, the “generic” sentinel), never absent. Import always resets it to that value. |
76
76
|`timestamp`|`uint32 (0–4294967295, chip epoch)`|**yes**|**Req**|**Req**|**Req**|**Req**| Chip encode timestamp — SECONDS since 2000-01-01 (TigerTag chip epoch, not Unix, not Firestore). |
77
+
|`tag_index`|`uint4 (0–15)`|**yes**| Opt | Opt | Opt | Opt | Chip i of n — which chip of the object this is, from 1 (chip byte +39 high nibble, protocol v2.2). 0 = unknown (any chip written before v2.2). Chip-only: a chipless record never carries it (dropped on import, as is any value outside 0–15). |
78
+
|`tag_count`|`uint4 (0–15)`|**yes**| Opt | Opt | Opt | Opt | How many chips the object carries (chip byte +39 low nibble, protocol v2.2): 1 = single, 2 = twin. 0 = unknown. A `tag_count` of 2 on a record with no `twin_tag_uid` is legal — the other chip simply was never scanned. Chip-only, same import rules as `tag_index`. |
Copy file name to clipboardExpand all lines: docs/firestore-schema.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -101,6 +101,8 @@ users/
101
101
deleted boolean
102
102
deleted_at number?
103
103
twin_tag_uid string? — linked twin chip's UID (the OTHER RFID chip on the same physical spool). NOTE: the field is `twin_tag_uid`, not `twin_uid`
104
+
tag_index number — which chip of the object this is, from 1 (chip byte +39 high nibble, protocol v2.2). 0 = unknown (chip written before v2.2, or chipless doc). Written on scan (from the chip) and on a guided burn.
105
+
tag_count number — how many chips the object carries (byte +39 low nibble): 1 = single, 2 = twin. 0 = unknown. A `tag_count` of 2 with no `twin_tag_uid` = the other chip has not been scanned yet.
104
106
message string? — user note (also the colour name for DIY/Cloud)
105
107
tags string[]? — user-defined free-form labels (Shopify-style). Studio metadata only, never written to the physical chip. Normalised (trimmed, ≤32 chars, case-insensitive dedup, ≤20/spool). Mirrored onto the twin spool so both chips of one physical spool share the same tags. Owner-write, no rule change needed (inventory has no field whitelist). Cross-app field — mobile ignores it until it implements tags
106
108
rfidListed boolean? — true once this UID has been recorded in rfidList/ (dedup marker; absent = not yet). Set by Studio's chip census / scan path. See rfidList/ below
0 commit comments