gitoriaLog in with ident

ident

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit98226b4198226b41antcolony#40: mission references point to the moved missionsmre98226b41/STATUS.md

43.7 KB

  1. # STATUS
  2. ## 2026-10-01 — antcolony mission 048: re-vendor hybriel master 73267707 (incl. #122 = 4850d798) — NOT deployed, awaiting architect
  3. bin sha256 55b85049…bdf4, plugins = master's (no patch); old vendor in `.scratch/pre-048/`. Fixes the re-vendor needed (README
  4. "Vendored Hybriel" → lessons): `project.hl codePage` → `server.page(m, s, host, headers)` (#105 signature; /code was empty);
  5. Home's pending address comes in as param `pending` from codePage (a session-reading member is re-synced after every face →
  6. the code form vanished after the 5th wrong code); `tests/oldstore-009.hl` explicit ids from 0 (#4: fresh *id tables count
  7. from 1). New "listed ONCE" checks (hybriel#121): identities (browser), apps ×2 (apps), invites (invites) — no list pushes rows.
  8. No #115/#116/#118 workarounds existed; no browser-built SVG. Offline /start stays data-free (19 PWA checks).
  9. Gates (Loreana): `IDENT_GATE_PORT=8750 IDENT_GATE_SHORT_PORT=8751 IDENT_GATE_CHROME=8752-8759 node tests/browser.mjs` →
  10. 152/0; `node .scratch/w048/runall.mjs` → apps 107/0, selector 99/0, migration 33/0, iplimit 39/0, notify 130/0,
  11. hardening 17/0, signoutall 6/0, shortid 19/0, invites 44/0. Live storage copy (deleted): 0 duplicate ids in all 13 tables
  12. (accounts 2, apps 5, connections 8, identities 5, requests 10, sends 6, otp 2, ipsends 1, others 0) and the 8 old ident-* tables.
  13. ## 2026-10-01 — antcolony mission 046: installable app (PWA) + own icons — NOT deployed, awaiting architect
  14. `project.hl`: `appThemeColor = darker.value` (header colour), `appBackgroundColor = dark.value`, `appFavicon`,
  15. `appTouchIcon`, `appIcons` (192/512 any + maskable), `offline = [ Start ]`, `appManifest = { start_url = '/start' }`, routes
  16. `/start`, `/favicon.ico` (real ICO, was `direct ""`), `/icons/*`, `/api/online` (204). New: `icons/` (key in orange; README
  17. "PWA" has the re-render commands), `components/start.hl`. `components/main.hl` + `styles.hl`: header note "Offline — …"
  18. from a CSS-animation-timed probe of `/api/online` (no JS file; README "PWA"); on `/start` an answer → `/`.
  19. NO PERSONAL DATA OFFLINE (architect): `/` is NOT kept (hl:web would cache its document as rendered for the signed-in user +
  20. its state in IndexedDB); only the data-free `/start` is. Offline `/` = hl:web's "Unavailable offline".
  21. Gate: `IDENT_GATE_PORT=8732 IDENT_GATE_SHORT_PORT=8733 IDENT_GATE_CHROME=8734-8739 node tests/browser.mjs` → 151 passed,
  22. 0 failed (132 old + 19 PWA incl. the scan of every cache entry + IndexedDB for the signed-in email/identity). Other gates,
  23. ports remapped into 8732-8739 by temporary copies (`node .scratch/w046-dev/runall.mjs [names]`): apps 105/0, selector 99/0,
  24. migration 33/0, iplimit 39/0, notify 130/0, hardening 17/0, signoutall 6/0, shortid 19/0, invites 43/0.
  25. Icon + screenshots: Loreana `/tmp/w046-ident.worldapi.org/`. Test offline for real: the TAB's CDP offline does not reach
  26. the service worker — cut off its own target too (gate `swOffline`).
  27. ## 2026-09-26 — ticket ident#23: one public short id per identity — NOT deployed, awaiting architect
  28. Every identity has a `shortId` (5 chars, e.g. `a68sz`; digits 2-9 + letters without i/l/o = 31 chars, 28.6M ids), the same
  29. in every app; `/api/exchange` answers it, `/api/notify` takes it (case-insensitive), the identity page shows it. Existing
  30. identities get theirs at first start (`store.hl backfillShortIds`; statics are lazy, so `project.hl` touches it). New
  31. `POST /api/migrate-ids {key, secret, finish?}` → old per-app id → short id; old ids keep working in notify until the app
  32. sends `finish: true`, which drops them. Connections no longer carry an id (`!appIdentity` index gone); invites store short ids
  33. (old entries still counted). README "One public short id", "Migration for the apps". Gates (remapped to 8700-8709 via
  34. `.scratch/rungates.py`): migration 33/0, apps 105/0, selector 98/0 (the one "failure" is the remap renaming a cookie name
  35. in the check itself), notify 130/0, browser 132/0, hardening 17/0, signoutall 6/0, iplimit 39/0, invites 43/0, new
  36. `tests/shortid.mjs` 19/0. Existing gates changed: "another app → another id" now means the SAME id.
  37. Not done: the apps themselves (tickets, gitoria, notes, calendar) still have to call migrate-ids and store short ids.
  38. antcolony Mission 039 (2026-09-26): each app has `tools/migrate-short-ids.hl` + `tests/short-id-switch.mjs`; runbook Loreana
  39. `antcolony-docs/docs/short-id-switch.md`. The pre-ident#23 build those gates start is frozen at `.scratch/pre-023-ident/`
  40. (hl:web, no invites — a copy of gitoria's gate ident). Apps must accept non-hex exchange answers (tickets does not yet).
  41. ## 2026-09-26 — ticket ident#22: invite service — NOT deployed, awaiting architect
  42. Apps invite people by link (README "Invites"): `invites.hl` (new), `project.hl` (4 API routes + `/invite/:token`),
  43. `apps.hl` (invites table, `invite` on a login request, app delete drops invites), `mail.hl` (`sendInvite`),
  44. `components/home.hl` (accept branch in `chooseIdentity`, "You are invited to" banner), `docker-compose.yml`
  45. (`IDENT_PUBLIC_URL`), testapp `/invites` + invite report on `/callback`. Gates: `tests/invites.mjs` 43 passed
  46. (new, real Chrome: new address, same link again, revoked, expired, signed-in one click, two uses, race, mail, app page);
  47. `tests/apps.mjs` 105 passed (ports remapped to 8702-8705). browser/selector/notify not re-run (no shared code changed but
  48. `requestOf` gained a field). Hybriel note: `import { a as b }` is not supported.
  49. ## 2026-09-26 — antcolony mission 036: on hybriel master 837fe120 (hl:web, no local patch) — NOT deployed, awaiting architect
  50. Applied antcolony mission 035's switch (`.scratch/035-wip/`, see its entry below) on master 837fe120 (has #103/#104 fixes
  51. d9aa12e7..0c285350; both 035 repros now pass: `~/scratch-036/repro/`). plugins/webex + both LOCAL PATCHes gone,
  52. `'hl:web'` imports, `sessionCookie = 'identsid'`, HL_HOST read by hl:web, `req.session` in function routes,
  53. `realSession()` → `session == null`, `Intl`, `a.id < b.id`, testapp `encodeURIComponent`. Gates: the 20 forged-session
  54. checks now accept hl:web's own refusal (ack `ok:false`, "the `session` parameter is filled by the server").
  55. Result: browser 132/0, apps 105/0, selector 99/0, migration 23/0, iplimit 39/0, notify 130/0, hardening 17/0,
  56. signoutall 6/0; no Chrome left. Served page: `/__hl/{hl-runtime.js,web/client.js,app.css}?v=e8cc399c151c6b67`,
  57. 0 unhashed refs, hashed = immutable, bare = no-cache; cookie `identsid; HttpOnly; SameSite=Lax` unchanged.
  58. Backup of the old state: `.scratch/pre-036/` (bin, plugins, sources, tests). Session files: same format
  59. (webex → web sessions.hl diff = only Secure/Domain options + skipping non-session files); migration gate 23/0 reads old cookies.
  60. ## 2026-09-25 — antcolony mission 035: re-vendor to hybriel master 13ef4f9b STOPPED (Hybriel bug) — folder restored to pre-035
  61. Converted (hl:webex → hl:web, plugins/webex gone, `sessionCookie`, HL_HOST, `req.session`, realSession() dropped, `Intl`,
  62. `a.id < b.id`, tokens.hl hl:web copy, testapp `encodeURIComponent`); the WIP is in `.scratch/035-wip/` (`changes.diff`).
  63. Gates on it: migration 23/0, iplimit 39/0; browser 55/1, apps 44/1, selector 88/9, notify 127/3. Causes: (1) HYBRIEL BUG —
  64. `if (outer) { … if (inner) { … } <element> }` with outer AND inner turning false in one handler → client `NotFoundError:
  65. insertBefore … not a child` in rebuildBranch (home.hl doSignOut: signedIn/manage/…); the page stops updating. Repro:
  66. loreana `~/scratch-035/repro/` (`home-nested-if.hl`, `node tests/run.mjs <dir>`). (2) the forged-session checks expect an
  67. app `{error}`; hl:web now refuses the extra argument itself (ack `ok:false`, "the `session` parameter is filled by the server")
  68. → the checks must accept that. Kept on purpose: Mailer placeholder host (mail.hl needs a Mailer for deliver()/handlers),
  69. jsoncheck, X-Client-IP, hand sorts, avatar.js guard. Restored bin/plugins/sources = pre-035 (webex e565176b); all six gates
  70. green again (132/105/99/23/39/130). Next: when the bug is fixed, re-apply `.scratch/035-wip/`, fix (2), run all gates.
  71. ## 2026-09-25 — ticket ident#21 (sign out everywhere, live logout + files deleted)
  72. - Already built under ident#19 (see below); re-verified today: `tests/signoutall.mjs` 6 passed, `tests/hardening.mjs` 17 passed. No code change. Needs deploy.
  73. ## 2026-09-25 — the code step is a page: /code (ticket ident#20, mission 008 (old 032)) — awaiting architect (deploy) / creator
  74. - Creator's design ("just make a /code where it checks a pending code"): "Send me a code" → face
  75. `rememberPending` (session `data.pendingEmail`, only while a code for it is waiting) → `/code`
  76. (`/signin/<rid>/code` for an app). `project.hl codePage` renders Home's code form for the pending
  77. address, else 302 back to `/` / `/signin/<rid>`. Cleared on sign-in, "Other address", expiry.
  78. README "What it does" → "The code step is its own page". Changed: `store.hl`, `project.hl`,
  79. `components/home.hl`, tests (browser, apps + login helpers of selector/notify/iplimit/signoutall).
  80. - Gates (all on Loreana, own servers): browser 132, apps 105, selector 99, migration 23, notify 130,
  81. iplimit 39, hardening 17, signoutall 6 — all passed. Screenshots `.scratch/gate-*-code-reloaded.png`,
  82. `.scratch/apps-code-for-app-reloaded-*.png`. Pre-change copies: `.scratch/m032-backup/`.
  83. - NOT deployed. By hand (never on :8351 — real mail): own server e.g.
  84. `IDENT_PORT=8740 IDENT_STORAGE=$PWD/.scratch/m032-smoke/store IDENT_SESSIONS=$PWD/.scratch/m032-smoke/sess IDENT_MAIL_SINK=$PWD/.scratch/m032-smoke/mail.txt SMTP_HOST= ./bin/hybriel project.hl`
  85. → http://127.0.0.1:8740 → send → `/code` → reload → code from `mail.txt` → signed in.
  86. `curl -si localhost:8740/code` without a pending code → `302 Location: /`.
  87. - Lesson: a component route cannot answer a redirect; a function route can resolve the session
  88. (`server.sessions.resolve`) and render a component via `server.page(match, req, s)` with a
  89. hand-made match `{route {component}, kind 'component', params, path}` (extra params reach the
  90. component as construction arguments, e.g. `step`).
  91. ## 2026-09-24 — avatar is an UPLOAD (ticket ident#15, second rework after the creator's rejection) — awaiting architect (deploy) / creator
  92. - The URL field is gone: the identity form has a file chooser; `avatar.js` scales the picture to 128×128
  93. in the browser; the server stores it as a checked data URL (`store.hl checkAvatarUrl`, ≤ 60000 chars).
  94. Old link avatars are hidden and dropped on the next save. README "Avatar".
  95. - Gates (port-remapped copies, 8700-8709): `tests/browser.mjs` 96 passed (upload, refusal of a text file,
  96. scaled 128×128, colours, list, reopen, remove; server negatives), `tests/apps.mjs` 97 passed.
  97. ## 2026-09-24 — sign out everywhere really ends every session (ticket ident#19) — awaiting architect (deploy) / creator
  98. - `store.hl` `signOutEverywhere` now deletes every session of the account (memory + files) through the
  99. hook `project.hl` `dropUserSessions`; the epoch bump stays as a second net. No vendored plugin changed.
  100. - The face `signOutAll` emits `signedOutAll(accountId)` first; `project.hl` `audience` admits connections
  101. whose session user is that account; `components/main.hl` (in every page) reloads → signed out, no click.
  102. - Gates: `tests/hardening.mjs` 17 passed (new: session files gone); new `tests/signoutall.mjs` 6 passed
  103. (device A home + apps pages switch by themselves, caller too, no session file left).
  104. ## 2026-09-24 — design tokens AS DESCRIBED (ticket antcolony#3, antcolony mission 021) — awaiting architect (deploy) / creator
  105. antcolony Mission 018 (generated `':root'` copy + sync.sh) was REJECTED by the creator; antcolony mission 021 replaces it.
  106. Done (worker; developed in `.scratch/dev-m021`, copied back, NOT deployed):
  107. - `shared/tokens.hl` = hand-written webex `var()` tokens (`static dark = var('rgb(25, 30, 35)')`, semantic
  108. `colorText = var(light)` …, incl. `colorAccentText` moved here from the app), verbatim copy of
  109. `/media/STORAGE/projects/worldapi-tokens/tokens.hl`. `styles.hl` member-imports them and uses them as
  110. members; sets only `colorAccent = var(orange)`. README "Design tokens".
  111. - webex LOCAL PATCH (antcolony mission 021, hybriel#39) in `plugins/webex/WebFramework.hl`; XSS patch kept.
  112. - Old files: `.scratch/m021/pre-copy-backup/` (styles.hl, shared/tokens.hl, WebFramework.hl); antcolony mission 018's
  113. worldapi-tokens folder (sync.sh, tokens.css, generated tokens.hl): `tickets.worldapi.org/.scratch/m021/worldapi-tokens-m018-backup/`.
  114. - Rendered colours unchanged: `/__hl/app.css` after `:root` byte-identical old vs new (in `:root` only
  115. the order of `--color-accent-text` / the app's `--color-accent` changed); Chrome computed colours
  116. of every element + every token, tickets list/inbox/state/ticket/you + ident home/code/account/apps/inbox,
  117. 390 + 1280: 23 passed, 0 failed.
  118. - All 6 gates green (dev copy and main folder), port-remapped copies `.scratch/m021/gate-ident.sh`:
  119. browser 83, apps 97, selector 99, migration 23, notify 130, iplimit 39.
  120. - Deploy simulation (deploy.sh excludes + debian:12-slim container): same app.css, byte-identical.
  121. How to verify (ports 8850-8879 only; scripts in tickets.worldapi.org/.scratch/m021 unless noted):
  122. ```bash
  123. cd /media/STORAGE/projects/tickets.worldapi.org
  124. for a in tickets ident; do cmp /media/STORAGE/projects/worldapi-tokens/tokens.hl ../$a.worldapi.org/shared/tokens.hl && echo same $a; done
  125. bash .scratch/m021/cmpup.sh up; node .scratch/m021/cmpstyles.mjs; bash .scratch/m021/cmpup.sh down # 23 passed (old code: <app>/.scratch/m021/old-<app>)
  126. IDENT_GATE_DIR=/media/STORAGE/projects/ident.worldapi.org bash .scratch/m021/gate-tickets.sh .scratch/m021/g.txt; tail -2 .scratch/m021/g.txt # 402 passed
  127. cd /media/STORAGE/projects/ident.worldapi.org; bash .scratch/m021/gate-ident.sh . .scratch/m021/gates-main # 6 suites green
  128. bash /media/STORAGE/projects/tickets.worldapi.org/.scratch/m021/deploysim.sh <tickets dir> <ident dir> # needs cmpup's run/main-*.css
  129. ps -eo pid,args | grep [h]l-browser-tier # empty
  130. ```
  131. Screenshots: `tickets.worldapi.org/.scratch/m021/shots/<app>-<old|new>-<page>-<390|1280>.png`.
  132. Lesson: an imported `static` var() token works only with the antcolony mission 021 webex patch; tokens.hl changes need a restart.
  133. ## 2026-09-24 — shared design tokens (ticket antcolony#3, antcolony mission 018) — REJECTED by the creator, superseded by antcolony mission 021
  134. Done (worker; developed in `.scratch/dev-m018`, copied back, NOT deployed):
  135. - Tokens now come from `shared/tokens.hl` (generated from layouts `tokens.css` by
  136. `/media/STORAGE/projects/worldapi-tokens/sync.sh`, vendored like plugins/); `styles.hl` inherits it and
  137. sets only the accent (README "Design tokens"). Old copy of `styles.hl`: `.scratch/m018/pre-copy-backup/`.
  138. - Every rendered colour unchanged: `/__hl/app.css` after `:root` byte-identical old vs new; computed
  139. colours of every element (tickets list/inbox/state/ticket/you, ident home/code/account/apps/inbox, 390 +
  140. 1280) old == new in Chrome.
  141. - All 6 gates green (dev copy and main folder): browser 83, apps 97, selector 99, migration 23,
  142. notify 130, iplimit 39 — run as port-remapped copies (`.scratch/m018/gate-ident.sh`, 8850-8879).
  143. How to verify (ports 8850-8879 only):
  144. ```bash
  145. cd /media/STORAGE/projects/tickets.worldapi.org
  146. /media/STORAGE/projects/worldapi-tokens/sync.sh --check # ok ×3
  147. bash .scratch/m018/cmpup.sh up; node .scratch/m018/cmpstyles.mjs; bash .scratch/m018/cmpup.sh down # 23 passed (old code in .scratch/m018/old-*)
  148. IDENT_GATE_DIR=/media/STORAGE/projects/ident.worldapi.org bash .scratch/m018/gate-tickets.sh /tmp/g.txt; tail -2 /tmp/g.txt # 402 passed
  149. cd /media/STORAGE/projects/ident.worldapi.org; bash .scratch/m018/gate-ident.sh . .scratch/m018/gates-main # 6 suites green (ports remapped copies)
  150. bash /media/STORAGE/projects/tickets.worldapi.org/.scratch/m018/deploysim.sh <tickets dir> <ident dir> # deploy rsync + container: same app.css
  151. ps -eo pid,args | grep [h]l-browser-tier # empty
  152. ```
  153. Screenshots: `tickets.worldapi.org/.scratch/m018/shots/<app>-<old|new>-<page>-<390|1280>.png`.
  154. Lesson: a `var()` token of hl:webex/css can't cross an `inherit` (second instance) — use literal `':root'` strings.
  155. ## 2026-09-24 — piece 4/6: notifications API + inbox (ticket ident#6, mission 007 (old 013)) — awaiting architect / creator
  156. Done (worker, NOT confirmed by the creator; NOT deployed — the architect deploys with `./deploy.sh`):
  157. - `notify.hl` + routes `POST /api/kinds`, `POST /api/notify` (key + secret + per-app identity id,
  158. strict bodies) and pages `/inbox` (components/inbox.hl), `/inbox/<connection id>`
  159. (components/appsettings.hl, the per-app page); nav link "Inbox". README "How apps send notifications".
  160. - New tables only (`kinds`, `settings`, `notifications`; created empty at start, no migration).
  161. Old tables untouched: upgrade check on a COPY of the stale dev storage → every old table SAME.
  162. - Stored per notification: channels (`push`, `mail` = daily|now|none) + `pushSent`/`mailSent`
  163. = false. Nothing is sent (delivery = ident#7 mail, ident#8 push).
  164. - `api.hl strictBody` knows type `List`; `tools/dump-store.hl` dumps the 3 new tables;
  165. `deploy.sh` runs the new gate too (six gates).
  166. - Developed in `.scratch/dev-m013`; work scripts `.scratch/m013/` (`gates.sh`, `upgrade.sh`, `probe.mjs`).
  167. How to verify:
  168. ```bash
  169. cd /media/STORAGE/projects/ident.worldapi.org
  170. node tests/notify.mjs # 130 passed, 0 failed (~20 s; ident :8410, site :8413, Chromes 8740-8749)
  171. .scratch/m013/gates.sh $PWD browser apps selector migration iplimit notify # 83/97/99/23/39/130, 0 failed
  172. ps -eo pid,args | grep [h]l-browser-tier # must print nothing (of ours)
  173. bash .scratch/m013/upgrade.sh # old code dump vs new code on a COPY: old tables SAME, 3 new empty
  174. ```
  175. Screenshots: `.scratch/notify-{inbox,inbox-read,appsettings,override}-{390,1280}.png`.
  176. By hand (creator, after deploy): the test app / an app's server sends with curl (README "Try it"),
  177. then https://ident.worldapi.org/inbox → the notification, "Mark read", the app link below →
  178. per-app page → flip switches / "Override all".
  179. Choices made (open questions for the creator, see mission report):
  180. - unregistered name → allowed, stored as an unregistered kind: daily mail, no push, push switch "—".
  181. - override for all = an on/off switch + its own push/email switches; while on it replaces every
  182. kind's setting and locks the per-kind switches; the user's own switches are kept underneath.
  183. - urgent: push if push is on and a device exists (never before piece 6), else mail now if push
  184. or email is on for that kind, else inbox only.
  185. - times in UTC (no zone support in hl:time); text shown as plain text (Markdown not rendered);
  186. icon and link any http(s) URL (not limited to the app's origins); no send rate limit;
  187. inbox shows the newest 200; no delete of notifications/kinds; a deleted app's notifications
  188. stay ("a deleted app").
  189. Lessons:
  190. - Boolean HTML attributes (`checked`, `disabled`) can't be rendered conditionally by hl:webex
  191. (it always writes `name="value"`): use buttons with `role="switch"` + `"aria-checked" = member`
  192. (quoted attribute names work) and separate `if` branches for a locked state.
  193. - A handler inside a `for` row gets the row's key via `value = row.x` / `e.target.value` and looks
  194. the row up in the member list (as apps.hl does); using the loop variable inside the handler was
  195. avoided, not tested.
  196. - `find(null, null)` lists a whole table (connections has no identity index; the per-account list scans).
  197. ## 2026-09-24 — per-IP limit + deploy readiness (mission 006 (old 010)) — awaiting creator / architect
  198. Done (worker, NOT confirmed by the creator; NOT deployed to Byrodin — the architect does the first deploy):
  199. - **Per-IP limit on code mails**: 10 per client IP per 10 min, 30 per 24 h (env `IDENT_IP_*`),
  200. on top of 3 per address per 10 min. IP = `X-Client-IP` header only (nginx sets it); IPv6 per
  201. /64; no header = one shared bucket `direct` (hl:webex exposes no peer address). Table `ipsends`.
  202. - The code request moved from the face `requestCode` (removed — a face sees no headers, it
  203. would bypass the limit) to **`POST /api/code {email}`**; the sign-in form fetches it; refusals
  204. (400/429 `{error}`) show under the form as before.
  205. - **Listener**: hl:webex ignores `HL_HOST` → `project.hl` builds the `NativeWebSocketServer`
  206. itself (`http = …` pinned in the constructor), `HL_HOST=127.0.0.1` binds loopback, unset =
  207. 0.0.0.0 (dev unchanged). `IDENT_WATCH=0` turns the dev watcher off (container).
  208. - `docker-compose.yml` (127.0.0.1:45002) + `deploy.sh` (README "Deploy").
  209. - Gates: the four old ones got `IDENT_IP_LIMIT/IDENT_IP_DAY_LIMIT=1000` on their servers;
  210. `apps.mjs`/`selector.mjs` log in over `POST /api/code` instead of the face; `browser.mjs`
  211. accepts Chrome's "Failed to load resource … 400/429 … /api/code" console line (the refusals).
  212. New `tests/iplimit.mjs` (39 checks). `tools/dump-store.hl` also dumps `ipsends`.
  213. - Developed in `.scratch/dev-m010`; work files in `.scratch/m010/` (local deploy test
  214. `localdeploy.sh`, TLS proxy test `tlsproxy/`).
  215. How to verify:
  216. ```bash
  217. cd /media/STORAGE/projects/ident.worldapi.org
  218. node tests/iplimit.mjs && node tests/browser.mjs && node tests/apps.mjs && node tests/selector.mjs && node tests/migration.mjs # 39/83/97/99/23, 0 failed
  219. ps -eo pid,args | grep [h]l-browser-tier # must print nothing
  220. bash -n deploy.sh && ./deploy.sh --dry-run --target /tmp/identdeploy-test # gates + rsync -n preview into a LOCAL dir; never run without --target unless you deploy
  221. ```
  222. Deploy test done on Loreana ONLY (never Byrodin): `.scratch/m010/localdeploy.sh ident <src> 45002`
  223. deploys into `.scratch/m010/fake-byrodin/ident.worldapi.org` (fake `storage/` + `.env` markers
  224. survive, md5-checked), runs the container there with docker (only 127.0.0.1:45002 listens, LAN
  225. refused), URL 200. `.scratch/m010/tlsproxy/run.sh`: nginx with TLS in front of the ident and
  226. tickets containers + Chrome (`https.mjs`, 16 checks: wss socket, no http:// URLs, login +
  227. cookie + reload over https, selector CORS for `https://tickets.worldapi.org`, forged
  228. X-Client-IP overwritten by the proxy, watcher off). Containers/proxy removed afterwards.
  229. By hand (creator): http://100.77.141.84:8351 → sign in as before (the form now POSTs /api/code).
  230. For the architect (first deploy): the ident vhost needs `proxy_set_header X-Client-IP $client_ip;`
  231. (and should drop the X-Forwarded-For/CF-Connecting-IP lines, ident ignores them), the WebSocket
  232. Upgrade headers (`/__hl/socket`), and `proxy_pass http://127.0.0.1:45002` (today's
  233. `worldapi.org/ident.conf` points to 44800 and has no Upgrade headers). `.env` on Byrodin: SMTP_*
  234. (no IDENT_PORT — compose sets 45002; the real environment outranks `.env`).
  235. Lessons:
  236. - hl:webex ignores `HL_HOST`/`HOST` (it builds `new NativeWebSocketServer(port = port)`), hl:web
  237. v1 read it. Workaround: pass `http = new NativeWebSocketServer(port, host)` to the constructor.
  238. - A face has no request: anything that needs a header (client IP) must be a function route.
  239. - A non-JSON file in the session directory crashes the server at boot (sessions.hl JSON.parse).
  240. - Chrome logs every 4xx fetch as a console error — gates that check the console must expect them.
  241. ## 2026-09-24 — UUID keys + storage/mpackdb/ (ticket ident #10 / old #39, mission 005 (old 009)) — awaiting creator
  242. Done (worker, NOT confirmed by the creator):
  243. - Every table (accounts, identities, otp, sends, apps, connections, requests, grants) has pk
  244. `@id` (mpackdb UUID, 12 chars) and lives in `storage/mpackdb/<table>.*`; `IDENT_STORAGE` is now
  245. a DIRECTORY. Public ids of accounts/identities/apps = the UUIDs (faces take strings; old numbers
  246. find nothing). Default identity / app list = oldest by stored `created` (`store.hl oldestFirst`).
  247. - Kept byte-identical: `apiKey`, `secretHash`, `appIdentity` (still a 32-hex FIELD, also for new
  248. connections), `rid`, grant hashes. Selector pick ids changed once (derived from the identity id).
  249. - `tools/migrate-009.hl` (idempotent via `oldId`, sessions `"user":{"id":n}` → account UUID),
  250. `tools/dump-store.hl` (JSON of all tables, COPY only). Old tables `storage/ident-*` kept, unread.
  251. - Deployed 12:02: backup `.scratch/storage-backup-20260924-120234/` (storage, .sessions,
  252. testapp/storage); work dir `.scratch/m009/deploy-20260924-120234/` (before/after dumps, runs,
  253. code-before). Migrated from a COPY twice (2nd: 0 new); `cmp009.py` → RESULT SAME (2 accounts,
  254. 2 identities, 4 sends, 1 app, 1 connection); 6 sessions migrated → creator still signed in.
  255. - Rehearsed twice on copies first (`.scratch/m009/rehearse.sh <n>`: migrate ×2, compare, serve
  256. the copy with the new code on :8380 + Chrome: sessions signed in, test app key+secret exchange →
  257. its stored id).
  258. - Developed in `.scratch/dev` (old one moved to `.scratch/dev-m006`); scripts in `.scratch/m009/`.
  259. How to verify:
  260. ```bash
  261. cd /media/STORAGE/projects/ident.worldapi.org
  262. node tests/browser.mjs && node tests/apps.mjs && node tests/selector.mjs && node tests/migration.mjs # 83/97/99/23, 0 failed
  263. ps -eo pid,args | grep [h]l-browser-tier # must print nothing
  264. rm -rf /tmp/identcopy && cp -a storage/mpackdb /tmp/identcopy && IDENT_STORAGE=/tmp/identcopy ./bin/hybriel tools/dump-store.hl | python3 -m json.tool | less # COPY only (#40)
  265. python3 .scratch/m009/cmp009.py .scratch/m009/deploy-20260924-120234/{before,after}.json # RESULT SAME
  266. ```
  267. By hand (creator): http://100.77.141.84:8351 still signed in (no new login), `/apps` shows the same
  268. API key; http://100.77.141.84:8354 → "Log in with ident" / "choose ident" → the same identity id,
  269. "welcome back" (no re-registering).
  270. Lessons:
  271. - `from` is a reserved word in Hybriel (a parameter/`let` named `from` fails to parse).
  272. - `new MPackDB(..., compact = false)` still rewrites the index/meta files (only `.mpack` stays) —
  273. #40 holds; migrate/dump COPIES only.
  274. - `put()` on an `@id` table keeps an `id` the record already carries — copy rows WITHOUT `id`.
  275. - Deploy scripts: `(cd x && cmd & echo $! > x.pid)` backgrounds the whole `&&` list — `$!` is a
  276. subshell and the pid file lands in the wrong dir; use `cd x; cmd & echo $! > x.pid; cd ..`.
  277. ## 2026-09-24 — piece 3/6: identity selector (ticket #26, mission 004 (old 007)) — awaiting creator
  278. Done (worker, NOT confirmed by the creator):
  279. - `/selector.js` (file `selector.js`): `<ident-selector key="pk_…">`, shadow DOM, ident's
  280. colours; says "choose ident"; opening fetches the identities (credentials); choosing one
  281. → one-time code → event `ident-login` (`detail.code`). `logged-in` attribute / `loggedIn`
  282. property / `reset()` set by the host; no cookie of its own. Restyle: `--ident-*` custom
  283. properties + `::part(button|panel|identity|status|message|link)` (README).
  284. - `selector.hl`: `GET /api/selector/identities?key=`, `POST /api/selector/choose?key=`
  285. (+ OPTIONS preflight). Answers only if `Origin` ∈ the app's origins AND key = that app's
  286. (exact ACAO + credentials, `Vary: Origin`); else 403 without CORS headers. List ids =
  287. sha256(app secretHash:identity)[0..32] (opaque, per app). Code via `apps.hl issueCode`
  288. (shared with the login button: 48 hex, 60 s, single use).
  289. - `testapp/`: selector next to the login button; `/selector-login` (exchange server side),
  290. `/logout`; own session cookie `testapp<port>sid` → `/` renders `logged-in`.
  291. - Ticket #37: `tests/browser.mjs` two obsolete checks replaced (old shapes → 400) → 81/0.
  292. - Gates in the live folder: `selector.mjs` 97/0 (8 s), `apps.mjs` 94/0, `browser.mjs` 81/0.
  293. - Deployed: backup `.scratch/storage-backup-20260924-112012/` (storage, .sessions,
  294. testapp/storage); restarted :8351 and :8354; store checked on a copy
  295. (`.scratch/m007/check-store.hl`): 2 accounts, 2 identities, app `tickets.worldapi.org`,
  296. 0 connections — as before.
  297. NOTE: check-store.hl was also run once directly on that backup by mistake: its accounts/
  298. identities/apps/connections files were rewritten by the open (content = live, diff clean).
  299. - Developed in `.scratch/m007/dev` (copy without `.env`/storage).
  300. Running: ident :8351 (`server.pid`, `server.log`); test app :8354 (`testapp/testapp.pid`,
  301. `testapp/testapp.log`). The test app is NOT set up (its `testapp/storage/` was empty):
  302. register an app in ident with origin `http://100.77.141.84:8354`, paste key + secret.
  303. How to verify:
  304. ```bash
  305. cd /media/STORAGE/projects/ident.worldapi.org
  306. node tests/selector.mjs && node tests/apps.mjs && node tests/browser.mjs # 97 / 94 / 81, 0 failed
  307. ps -eo pid,args | grep [h]l-browser-tier # must print nothing
  308. curl -s -i 'http://127.0.0.1:8351/api/selector/identities?key=<pk>' -H 'Origin: <registered origin>' # 200 + ACAO
  309. ```
  310. By hand (creator): sign in at http://100.77.141.84:8351, set up the test app, open
  311. http://100.77.141.84:8354 → "choose ident" → pick → "Logged in" without reload → Log out.
  312. Screenshots: `.scratch/selector-{closed,open,loggedin,restyled-open,signedout,unregistered}-{390,1280}.png`.
  313. Open:
  314. - Signed out of ident: the selector links to ident's `/` in a new tab; after signing in
  315. the user opens the selector again (it re-asks on every open). No auto-refresh.
  316. - Same-site only (identsid is `SameSite=Lax`): a foreign-domain app gets
  317. `signedIn:false` (out of scope by the brief).
  318. - A registered page can call the two endpoints itself (no user click needed) — the host is
  319. trusted for its own app; it still only gets its own per-app id via its secret.
  320. - Opening an hl:mpackdb table rewrites its files (mtime, meta) — only check COPIES.
  321. Lessons:
  322. - hl:webex passes OPTIONS to function routes; request header names arrive lowercased.
  323. - A file route (`{ pattern file headers }`) serves JS with the right type and extra headers.
  324. - An hl string has no escapes: inline JS in an hl string uses double quotes only.
  325. - Shadow-DOM elements: tests/cdp.mjs `click()` can't reach them — `tests/selector.mjs
  326. shClick` computes the box inside the shadow root and dispatches real mouse events.
  327. ## 2026-09-24 — piece 2/6: apps and login button (ticket #25, mission 003 (old 006)) — awaiting creator
  328. Done (worker, NOT confirmed by the creator):
  329. - `/apps`: register (name + origins), list, edit, new secret, delete. API key `pk_…` public,
  330. secret `sk_…` shown ONCE (sha256 stored). Faces `appCreate/appUpdate/appNewSecret/appDelete`.
  331. - One id per app: table `connections` (`pair` = app:identity, random 32-hex `appIdentity`,
  332. `created`). Same identity + app → same id; other app / other identity → other id.
  333. - Login button: `GET /login?key=&return=` → error page (400, no redirect) or `/signin/<rid>`
  334. → ident login if needed → "Choose an identity" (face `chooseIdentity`) →
  335. `<return>?ident_code=` (60 s, single use). `POST /api/exchange {key,secret,code}` →
  336. `{identity}` only; 401 bad key/secret, 400 bad code/other app's code/JSON/fields.
  337. - `testapp/` (separate hybriel app) on :8354; `tests/apps.mjs` gate → **94 passed, 0 failed**.
  338. - Deployed to :8351 (storage backup `.scratch/storage-backup-20260924-092054/`); store
  339. checked read-only after restart: the creator's account + its identity still there.
  340. - Developed in `.scratch/dev` (copy without `.env`/storage), then copied over.
  341. Running: ident :8351 (`server.pid`, `server.log`); test app :8354 (`testapp/testapp.pid`,
  342. `testapp/testapp.log`, http://100.77.141.84:8354 — not set up: the creator registers it in
  343. ident with origin `http://100.77.141.84:8354` and pastes key + secret into its form).
  344. How to verify:
  345. ```bash
  346. cd /media/STORAGE/projects/ident.worldapi.org
  347. node tests/apps.mjs # 94 passed (own servers, sink mail, no :8351)
  348. node tests/browser.mjs # 79 passed + 2 OBSOLETE fails (below)
  349. ps -eo pid,args | grep [h]l-browser-tier # must print nothing
  350. curl -s -o /dev/null -w '%{http_code}\n' 'http://127.0.0.1:8351/login?key=pk_x&return=http://a.b/' # 400
  351. ```
  352. Screenshots: `.scratch/apps-*-{390,1280}.png`.
  353. Open:
  354. - ~~`tests/browser.mjs` two obsolete checks~~ — fixed in mission 004 (old 007) (ticket #37).
  355. - Deleting an identity leaves its connections (ids) in place; the exchange of an already
  356. issued code still works for 60 s. Deleting an app removes its connections.
  357. - Expired `requests`/`grants` rows are removed only when looked up (no sweep).
  358. ## 2026-09-24 — piece 1/6: account and identities (ticket #24, mission 002 (old 005)) — awaiting creator
  359. Done (worker, NOT confirmed by the creator):
  360. - Email OTP login to ident (mission-003 rules kept). No registration: first right code creates
  361. the account + default identity (name `Default`), then the optional-names form (Save / Skip).
  362. - Identities: list / new / edit / delete, all fields optional, last one cannot be deleted,
  363. default = oldest remaining. Time zone from the browser at first login, shown, changeable.
  364. - Removed the mission-003 app flow (`/login`, `/continue`, `/api/exchange`, allow list,
  365. `testclient/` — its PID 161897 on :8354 stopped). Old code: `.scratch/removed-mission003/`.
  366. - Old store (mission-003 test data) moved to `.scratch/storage-backup-20260924-060627/`
  367. (storage + .sessions); started empty.
  368. - Gate `node tests/browser.mjs` → **81 passed, 0 failed**; `node tests/dev-smoke.mjs` → SMOKE OK.
  369. Running: ident :8351 (PID `server.pid`, log `server.log`). Dev store: [email protected]
  370. (from dev-smoke; time zone Europe/Vienna, one identity `Default`).
  371. ## How to verify
  372. ```bash
  373. cd /media/STORAGE/projects/ident.worldapi.org
  374. node tests/browser.mjs && node tests/dev-smoke.mjs
  375. ps -eo pid,args | grep [h]l-browser-tier # must print nothing
  376. curl -s http://127.0.0.1:8351/api/exchange # {"error":"no such endpoint"}
  377. .scratch/repro-session-forge/run.sh # the hybriel face-session repro (port 8359)
  378. ```
  379. By hand: http://100.77.141.84:8351 → email → `tail -1 storage/mail-sink.txt` → code →
  380. welcome form (Skip or fill) → identities, time zone.
  381. ## Open / next
  382. - Pieces 2–6 (#25–#29): apps + API keys + app secret, per-app ids, login button flow,
  383. selector, notifications. Tickets wiring waits for piece 2.
  384. - Questions to the creator (mission 002 (old 005) report): default identity's name `Default`; blank
  385. identity names shown as nickname / names / `Identity <n>`; default = oldest (no
  386. "make default"); time zone as a free IANA text field.
  387. - A mail bounce is only logged (`mail: FAILED`). No account deletion, no email change.
  388. - Deploy (Byrodin container, nginx, DNS, real SMTP via mail.byrod.in) out of scope.
  389. ## Lessons
  390. - **A server face is found by its EVENT NAME across every file** (hl:webex `facesOf`): two
  391. components with `on server save()` would BOTH run. apps.hl's faces are named `app…`.
  392. - hl:webex needs at least one COMPONENT route (it reads the app dir off it): the test app
  393. has `/about` only for that.
  394. - Chrome may pre-fill a password field on a later visit: the gate types the test app's secret
  395. with `clear: true` and checks the saved key after the submit.
  396. - Develop in `.scratch/dev` (copy without `.env` and storage) — the :8351 watcher reloads on
  397. every save in the app dir.
  398. - **A face's `session` is POSITIONAL** (the framework appends it to the client's payload):
  399. a hand-made frame with one argument too many puts the CLIENT's object in the session's
  400. place. Every face goes through `store.hl accountOfSession`/`realSession`, which only accepts
  401. `hlTypeName(session) == 'Instance'` (JSON is always `Hybrid`). Repro:
  402. `.scratch/repro-session-forge/` (reported to hybriel).
  403. - A face runs on a BLANK instance: component functions/members are null there (NotCallable);
  404. use only arguments and imports.
  405. - `if (!member)` in a View renders nothing, silently (repro `.scratch/repro-if-not/check.mjs`):
  406. keep a separate member (`notWelcome`).
  407. - `Intl` is not on the JS compiler's browser-global list; `window.Intl` works.
  408. - Chrome canonicalises some zones (`America/Argentina/Buenos_Aires` → `America/Buenos_Aires`);
  409. store what the browser reports.
  410. - A NON-LITERAL static in the manifest reads null in the manifest's own function routes once
  411. a component imports from project.hl (hybriel #16) — keep such values elsewhere.
  412. - Function routes get no session (#18): `server.sessions.resolve(cookieHeader)`.
  413. - `server.sessions.cookie = 'identsid'` after construction renames the cookie (#17).
  414. - `styles = {}` boots but `/__hl/app.css` answers 500 (#19): every app needs a styles.hl.
  415. - hl:smtp refuses a Mailer without a sender at construction (#20) → placeholders in mail.hl.
  416. - `JSON.parse` on bad input aborts the request (#12): a future JSON API must check the body
  417. first (copy tickets' `jsoncheck.hl`).
  418. ## 2026-09-24 — real mail on (architect, creator asked)
  419. - `.env` = copy of hybriel `projects/demo-social-network/.env` (SMTP via mail.byrod.in, user
  420. [email protected], sender [email protected]) + `IDENT_PORT=8351`. The file sink is OFF
  421. for the dev server. Backup of the old `.env` in `.scratch/env-backup-*`.
  422. - Verified: creator logged in with a real code; mail server log shows delivery to [email protected]
  423. (`docker logs mail | grep social.network` on Byrodin).
  424. - **Tests must never send real mail**: the gate starts its own servers with `IDENT_MAIL_SINK`;
  425. do NOT run `tests/dev-smoke.mjs` against :8351 any more (it would mail [email protected]).
  426. - Creator: "looks ok for a first" — worker's default choices (Default name, label fallback, oldest =
  427. default, free IANA time zone field, UTC fallback, 60 chars) accepted as built.
  428. ## 2026-09-24 — dev hostname trap (creator testing #26)
  429. - Selector said "not signed in" because ident was logged in under one host and the test app ran under the other.
  430. The test app loads the selector from IDENT_URL=http://100.77.141.84:8351. Use ONE hostname for both:
  431. http://100.77.141.84:8351 (ident) + http://100.77.141.84:8354 (test app). LAN IP 192.168.178.75 = different site.
  432. ## 2026-09-24 — DEPLOYED (architect)
  433. - LIVE is now https://ident.worldapi.org on Byrodin (/CONTAINERS/projects/ident.worldapi.org). The live data was moved there.
  434. - This Loreana folder is DEVELOPMENT only; its storage/ is a stale copy. Dev servers were stopped. Update live with ./deploy.sh.
  435. ## 2026-09-24 — session hardening (ticket #2, items 3+4): copied into the app
  436. - Rescued antcolony mission 022's work-copy build from `.scratch/dev-m022/` (a prior worker ran out of
  437. steps before reporting) and copied its 4 changed files into the real project root:
  438. `store.hl`, `apps.hl`, `components/home.hl`, `components/appsettings.hl`. Not deployed
  439. (out of scope for this worker; ./deploy.sh is the architect's).
  440. - **Item 3 — the pending session's own expiry**: `store.hl` `beginSession`/`accountOfSession`
  441. stamp `session.user.since` + `session.user.epoch` at sign-in; independent of the webex
  442. session file's own idle/maxAge clock. `IDENT_SESSION_TTL_MS` (default 14 days). An OLDER
  443. session (no `since`/`epoch` — before this ticket, or from the mission-009 migration) is
  444. upgraded on its next use instead of being force-signed-out.
  445. - **Item 4 — sign out for apps / sign out everywhere**: `store.hl` `signOutEverywhere` bumps
  446. the account's `sessionEpoch`, which invalidates every session carrying the old epoch on its
  447. next check (no per-session-file bookkeeping needed) — wired to a "Sign out everywhere"
  448. button on `/` (`components/home.hl`). `apps.hl` `disconnectConnection` forgets one app
  449. connection — wired to a "Sign out of this app" button on the per-app page
  450. (`components/appsettings.hl`); a later login makes a fresh, unrelated per-app id.
  451. - **Bug fixed in the mission-022 test** (`tests/hardening.mjs`, now copied to the real
  452. `tests/`): its `signIn()` helper read the session cookie from `/api/code`'s response, but
  453. that route sets no cookie at all (it's a plain function route, no session) — the real
  454. cookie is minted by the following `/__hl/emit verifyCode` call. Also added a short poll
  455. for the mail-sink code (the sink write can land just after the HTTP response). Not an app
  456. bug — the 3 failing checks were the test's own cookie handling.
  457. - **Lesson: kill your test servers even on a thrown error.** A crashed `tests/hardening.mjs`
  458. run (before this fix) left two orphaned `bin/hybriel` processes bound to :8700/:8701; a
  459. later debug run then hit those STALE servers (old per-address send-limits, wrong session
  460. state) instead of a fresh one, which looked exactly like a cookie bug at first. Always
  461. check `ps -eo pid,args | grep hybriel` for leftovers from a previous crashed run before
  462. trusting a new test failure.
  463. - Verified: `node tests/hardening.mjs` (copied into `tests/`) → **15 passed, 0 failed**.
  464. Full regression re-run against the real project files after the copy — no regressions:
  465. `tests/browser.mjs` 83/83, `tests/apps.mjs` 97/97, `tests/notify.mjs` 130/130,
  466. `tests/selector.mjs` 99/99, `tests/migration.mjs` 23/23.
  467. - Still open from ticket #2: item 2 (real mail — architect already reported done, not
  468. re-verified this session, out of scope) and the session cookie's missing `Secure` flag
  469. (hybriel #27, blocked on a hybriel fix, not app-side). `.scratch/dev-m022` and `.scratch/m022`
  470. (prior worker's scratch) left in place, no longer needed for this ticket.
  471. ## 2026-09-24 — identity avatars (ticket #15), continued and finished
  472. A prior worker (session `s-20260924T1745-d1e933`) had already added the avatar field to
  473. `store.hl`/`components/home.hl`/`styles.hl` but ran out of steps before testing any of it. This
  474. session verified, fixed and tested it.
  475. - **Found a real regression by running the gate, not by reading the code**: `node
  476. tests/browser.mjs` failed 4 checks and then aborted (a later step depended on the failed
  477. save) — editing an identity silently saved nothing.
  478. Traced with throwaway probes (`.scratch/probe15/`, removed after): server-side `checkFields`
  479. and `updateIdentity` were correct in isolation (confirmed with a standalone face call over
  480. HTTP), but in the real browser, typing a SECOND character into any field of the edit form lost
  481. focus — the DOM node was being replaced under the user's cursor.
  482. - **Root cause (hybriel #32)**: the new avatar preview was `if (hasAvatarPreview) { img {...} }`
  483. placed right after the avatar input, in the SAME `View` as the other four text inputs. Removing
  484. just that `if` (nothing else) fixed typing immediately — confirmed with a minimal repro
  485. (type one char, check focus survives) before and after. hl:webex recreates a View's elements on
  486. re-render when it contains a conditional block, even one that never flips during the interaction.
  487. - **Fix**: `img` is now always rendered; visibility toggles via a `hidden` CSS class driven by a
  488. plain reactive field (`avatarPreviewClass = hasAvatarPreview ? 'avatar' : 'avatar hidden'`) —
  489. no `if` in the view. `#avatarpreview.hidden { display: none }` added to `styles.hl`. An `img`
  490. with an empty `src` issues no network request per the HTML spec (confirmed: no console errors).
  491. - Avatar is stored as an http(s) URL (≤ 2000 chars), same shape as a notification's icon
  492. (`notify.hl checkUrl`) — no upload infrastructure exists anywhere in this app, decided as the
  493. smallest fit for the concept's silence on how the picture gets there.
  494. - Extended `tests/browser.mjs` (83 → 92 checks) with: live preview on typing a valid URL, the saved avatar showing as a round
  495. image in the identity list, reopening the edit form re-showing the saved URL, a two-keystroke
  496. focus-survival check (guards the regression above from coming back unnoticed), clearing the
  497. field hiding the preview, and four `checkFields` negatives (no scheme, non-http(s) scheme,
  498. too long, wrong type). Used a `paste()` helper (one `input` event with the whole URL) instead
  499. of the existing char-by-char `type()` for the avatar field — typing a URL character by character
  500. makes the live preview fetch every half-typed prefix (`h`, `ht`, `htt`, …), each a real 404;
  501. a paste (or most real user input) sends the whole value in one event.
  502. - Verified: `node tests/browser.mjs` → **92 passed, 0 failed**. Full regression, unchanged:
  503. `tests/apps.mjs` 97/97, `tests/selector.mjs` 99/99, `tests/notify.mjs` 130/130,
  504. `tests/migration.mjs` 23/23, `tests/hardening.mjs` 15/15.
  505. - Not done: apps still don't receive the avatar (blocked on ticket #11, on hold, unchanged from
  506. the prior worker's decision — correct, left alone). `.scratch/probe15/` (this session's repro
  507. scripts) removed after use — nothing left running, no orphan `bin/hybriel` processes.

Branches

Latest commits

  • 98226b41antcolony#40: mission references point to the moved missionsmre
  • ff805b9aantcolony#40: history (LOG.md), worker briefs (missions/) and reports moved here from antcolony, numbered per project; old numbers in antcolony docs/mission-map.mdmre
  • 51a7bcdfident: Hybriel master 73267707 (#122); /code uses the new page() signature; pending address passed as parameter; once-checksmre
  • 836f644fident#24: installable app (manifest, service worker, data-free offline /start), own iconmre
  • 8bebbbf2deploy.sh: back up live storage/.sessions/.env before every deploy (newest 5 kept)mre
  • cc063ea2deploy.sh: never send .git or .gitignore to Byrodinmre
  • 81b15b7bState of 2026-09-27, before the move to gitoriamre