gitoriaLog in with ident

calendar

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit14ba08c714ba08c7antcolony#40: mission references point to the moved missionsmre14ba08c7/README.md

8.3 KB

  1. # calendar.worldapi.org
  2. The creator's calendar (CONCEPT.md), in Hybriel on hl:web. The month view at `/` — prev / next buttons on top, month name
  3. and year between them, today marked, weeks start on Monday, names in the browser's language — and, since ticket #2,
  4. **login with ident and private events**. https://calendar.worldapi.org
  5. ## Use
  6. - Signed out: the month view and "Log in with ident" (top right; the identity selector or the button).
  7. - Signed in: click a day to add an event, click an event to edit or delete it. An event has a title, "At a time" (from /
  8. to, date and time) or "All day" (from / to, dates), a place and notes. It shows on every day it covers (a day shows four
  9. chips, the fourth says "+N more"). Only the owner sees, changes or deletes an event.
  10. - Events are stored as **WorldAPI Events** (https://worldapi.org/standards/event): `$type $version $kind $title
  11. $description $start $end $timezone $location $status $visibility $created $updated` plus `owner` (users `@id`). Timed
  12. events: local wall-clock `$start`/`$end` + `$timezone` (the browser's); all-day: `$kind = 'allday'`, date `$start`, exclusive
  13. date `$end` (left out for one day); `$created`/`$updated` are UTC instants; `$visibility` is always `private`.
  14. - **Short ids (ident#23, antcolony mission 039)**: `users.identity` holds what ident's exchange answers — since ident#23 the identity's
  15. public 5-character short id (`a68sz`), before that the per-app id (32 hex); `users.hl isIdentId` accepts both (the old
  16. `isHex` check refused short ids). The switch: one-off `tools/migrate-short-ids.hl` (old → short id, idempotent, never
  17. `finish`), gate `node tests/short-id-switch.mjs` (ports 8722/8723, no browser), runbook
  18. `antcolony-docs/docs/short-id-switch.md` (Byrodin: `/CONTAINERS/projects/antcolony/docs/short-id-switch.md` once synced).
  19. ## Reminders and notifications (ticket #4)
  20. - **Reminder settings** (button under the month, signed in): the calendar's default reminders — 1 hour before and the day before at
  21. 20:00 until changed. Every event without reminders of its own gets them. In an event, "Calendar's" / "Own" chooses; "Own" is a list
  22. of rows (N minutes before, N hours before, N days before at HH:MM), also none at all.
  23. - Stored as WorldAPI Event `$reminders` (`{ $before: 'PT1H' }`, `{ $days_before: 1, $time: '20:00' }`); no `$reminders` = inherit; the
  24. defaults are the Calendar's `$reminders` in `storage/mpackdb/settings.db` (one row per owner).
  25. - The page keeps the events of the next days with the reminders that apply (`soon`, part of the page state — the offline layer stores it)
  26. and sets one browser timer per reminder of the next 7 days (`arm()`; set again after every save / delete / paging and every 10 minutes
  27. of use). A timer shows the notification (hl:web `notify`, through the service worker). "Turn on notifications" is the click the browser
  28. wants before it allows them.
  29. - **Offline:** the timers need no network, and the offline page has `soon`. An event saved while the server cannot be reached shows at once,
  30. its reminders are set, and the save waits in hl:web's emit queue until the connection is back.
  31. - **Limit (Hybriel):** a timer lives while the app (or its tab) is open; a fully closed app cannot be woken without a server push (later,
  32. via ident's push notifications, ident#8). `notifyAt` cannot cancel, so `arm()` uses `setTimeout` directly and calls `notify`.
  33. - Code: `components/month-view/reminders.hl` (rows ↔ `$reminders`, describe, time-zone instants, the plan) shared by `events.hl` (settings
  34. table, `upcoming`) and `month-view.hl` (editor, timers).
  35. ## Layout
  36. - `project.hl` routes, the ident login return (`/login/callback`, `/login/failed`) · `styles.hl` all CSS (tokens from
  37. `shared/tokens.hl`, accent = light blue) · `components/main.hl` shell with the login · `components/calendar.hl` the page
  38. and the faces `calLoad` / `calSave` / `calDelete` · `components/loginfailed.hl`.
  39. - `users.hl` users table (`storage/mpackdb/users.db`, ident identity → user `@id`) and the ident exchange ·
  40. `events.hl` events table (`storage/mpackdb/events.db`, index `owner`), strict validation, every function takes the owner.
  41. - `components/month-view/` the month view, vendored from components.hybriel.worldapi.org and EXTENDED here (events on the
  42. days, the editor; `dates.hl` = date helpers shared with the server; it carries its own `Style`). Re-vendoring needs these changes carried over.
  43. - `login.js` ident selector ↔ shell bridge (the only hand-written JavaScript). The month view reads the browser's today / language / time zone itself (Hybriel `Date` / `Intl` in a handler, on the first pointer / focus / touch), no `month-view.js`.
  44. - PWA (ticket #3): installable and offline through hl:web's own support — `appIcons`, `appThemeColor`, `offline = [ Calendar ]` in project.hl (manifest link in the head, `/__hl/manifest.webmanifest`, `/__hl/sw.js`); icons in `icons/`. No JavaScript of ours.
  45. - `bin/hybriel` + `plugins/` (core crypto data fetch fs http http1 mpackdb proc time web) are vendored = hybriel **master
  46. ff51cf46** (2026-10-01, antcolony mission 048: #113 mpackdb generated ids redrawn while taken, #115/#116 function-literal members
  47. reachable from faces, #118, client SVG namespace, hl:markdown #111; earlier #103–#106, #94, #83, #82, #95–#97). Built from a
  48. read-only `git archive master` (`zig build -Doptimize=ReleaseFast -Dtarget=x86_64-linux-gnu.2.39` in `native/`, zig =
  49. hybriel's `native/zig-toolchain` link), sha256 `ab7c3080…4b1d2f`. **No local patch**: re-vendor = copy binary + the
  50. plugins above, run both gates. Previous copy (e6720b1f): `.scratch/pre-048/`.
  51. - `components/calendar.hl` `validWindow` / `soonOf` are plain members called from the server faces (no `static` since #115/#116,
  52. antcolony mission 048; the gate checks both).
  53. - Language of the first render (calendar#6): `components/calendar.hl` declares `headers = null` (hybriel #105) and hands
  54. `headers['accept-language']` to `MonthView { acceptLanguage = requestLanguage }`; `names.hl` knows en de fr es it nl pt,
  55. any other → neutral names until the browser fills in its own. Names written by the server stay while paging.
  56. - Reminder timers: `arm()` creates the `setTimeout` closure inline in its `while` loop — `let p` is a new binding per pass
  57. (hybriel #106). On an older Hybriel the closures shared `p` and only the last reminder fired (antcolony mission 037 proved it:
  58. gate on 13ef4f9b → "the notifications came on time" FAIL, only "Has its own reminder" came).
  59. ## Run, test, deploy
  60. - `CALENDAR_PORT=8700 ./bin/hybriel project.hl` (env: `CALENDAR_WATCH=0` no watcher, `HL_HOST`, `CALENDAR_SESSIONS`,
  61. `CALENDAR_STORAGE`, `CALENDAR_PUBLIC_URL` default https://calendar.worldapi.org, `IDENT_URL`, `IDENT_EXCHANGE_URL`,
  62. `IDENT_API_KEY`, `IDENT_API_SECRET` — `.env` beside `project.hl`, never read by workers). A login needs the ident key.
  63. - `node tests/browser.mjs` — the gate: own ident (a copy without `.env`), own server + storage, headless Chrome
  64. (ports 8700 app, 8701 ident, 8702–8709 Chrome; `CALENDAR_GATE_PORT`, `CALENDAR_GATE_IDENT_PORT`, `CALENDAR_GATE_CHROME`).
  65. Second gate: `node tests/short-id-switch.mjs` (ports 8722/8723; `CALENDAR_SWITCH_IDENT_PORT`, `CALENDAR_SWITCH_PORT`).
  66. `GATE_SKIP_EVENTS=1` skips the events part (40 checks run instead of 76, ~1.5 min instead of ~4). The language checks (`languagePart`)
  67. open a tab per language with CDP `Network.setExtraHTTPHeaders` Accept-Language de / en and the browser's own language
  68. (Intl locale + navigator.language) set to the OTHER one; first page, server HTML, next/next/prev.
  69. - `./deploy.sh` on Loreana (architect): gate → backup → rsync → `docker compose up -d --build` on Byrodin (127.0.0.1:45005).
  70. ## First deploy of ticket #2 (architect)
  71. Register the app in ident with the origin `https://calendar.worldapi.org` and put `IDENT_API_KEY` / `IDENT_API_SECRET`
  72. into `.env` on Byrodin (as notes does), otherwise the login button has no key.
  73. ## History and worker briefs
  74. - `LOG.md` — append-only history, one dated line per step (moved here from the antcolony LOG on 2026-10-01).
  75. - `missions/NNN-*.md` — worker briefs for this app; `reports/NNN-*.md` — their reports (same name). Numbered per
  76. project since 2026-10-01 (antcolony#40); older text, code comments and commits use the old antcolony numbers →
  77. map: `/media/STORAGE/projects/antcolony-docs/docs/mission-map.md` (Byrodin: `/CONTAINERS/projects/antcolony/docs/mission-map.md`).

Branches

Latest commits

  • 14ba08c7antcolony#40: mission references point to the moved missionsmre
  • 99c73346antcolony#40: history (LOG.md), worker briefs (missions/) and reports moved here from antcolony, numbered per project; old numbers in antcolony docs/mission-map.mdmre
  • 76edaa62calendar: Hybriel master ff51cf46 (re-vendor round, static workaround removed)mre
  • 90a3fc2cdeploy.sh: back up live storage/.sessions/.env before every deploy (newest 5 kept)mre
  • 6722b72ddeploy.sh: never send .git or .gitignore to Byrodinmre
  • be099807State of 2026-09-27, before the move to gitoriamre