code wiki / _hdl_build / nx_reader_sync.nx
nx_reader_sync.nx
buildroot/runtime/_hdl_build/nx_reader_sync.nx
about
nx_reader_sync.nx -- R1 SYNC SPINE (beat-Kindle ladder #1; census cells SC01/SC37): per-USER cross-device
reading position for the library, behind THE WALL. Whispersync-class resume with a sovereign twist:
TEXT books -> AUTO-position: the daemon already serves every chapter fetch behind the wall, so recording
"last chapter opened" per (user, book) costs ZERO client changes -- the zero-JS text reader
stays zero-JS (census SC59 preserved) and still syncs across devices.
COMICS/scans -> EXPLICIT position: the zoom viewer (authed JS by design) POSTs {"page":N} and GETs it back
on open, so a phone resumes exactly where the desktop left off.
Storage: reader/<slug>/pos_<ukey>.json (client JSON stored VERBATIM, atomic tmp+rename, last-write-wins) +
reader/<slug>/auto_<ukey>.txt ("<chapfile>\t<epoch>"). <ukey> = sanitized handle + fnv32-hex8 of the RAW handle
(deterministic per user, collision-safe after sanitize, path-safe by construction). The user handle comes from
nx_sa_validate_handle at the wall -- identity is the AUTH layer's, never a client claim.
FAIL-CLOSED: slug via zs_slug_safe -> 403; body cap 2048 -> 413; auto-record NEVER breaks the book serve
(any doubt -> silent skip). Lib (no main); nx_reader_sync_gate drives the handlers in-process.
license_tier: ORIGINAL
dependencies 2 imports · 2 importers
imports: nx_syscalls.nxnx_reader_zoomserve.nx
imported by: nx_media_server.nxnx_reader_sync_gate.nx
structs
| none |
consts
| 17 | const SY_MAGIC_16777619: i64 = 16777619 |
| 18 | const SY_MAGIC_1152: i64 = 1152 |
| 20 | const SY_BODY_CAP: i64 = 2048 |
| 21 | const SY_ANN_CAP: i64 = 65536 // annotations = the user's whole list as one verbatim JSON doc (LWW, atomic) |
functions
| 25 | func sy_user_key(handle: *u8, hn: i64, out: *u8) -> i64 |
| 55 | func sy_write_atomic(path: *u8, data: *u8, n: i64) -> i64 |
| 67 | func sy_read_small(path: *u8, buf: *u8, cap: i64) -> i64 |
| 77 | func sy_path(slug: *u8, kind: *u8, ukey: *u8, ext: *u8, out: *u8) -> i64 |
| 90 | func sy_handle_pos_get(cfd: i64, p: *u8, plen: i64, ukey: *u8) -> i64 |
| 127 | func sy_handle_pos_put(cfd: i64, p: *u8, plen: i64, req: *u8, body_off: i64, body_len: i64, ukey: *u8) -> i64 |
| 166 | func sy_handle_ann_get(cfd: i64, p: *u8, plen: i64, ukey: *u8) -> i64 |
| 183 | func sy_handle_ann_put(cfd: i64, p: *u8, plen: i64, req: *u8, body_off: i64, body_len: i64, ukey: *u8) -> i64 |
| 215 | func sy_record_auto(p: *u8, plen: i64, ukey: *u8, now_s: i64) -> i64 |