gitoriaLog in with ident

ident

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Branchmain5fdbb6b2ident mission 009: report — scratch folder notemremain/project.hl

8.5 KB

  1. // project.hl — ident.worldapi.org: THE MAP. Config, routes and wiring; the logic lives in lib/. Concept: CONCEPT.md
  2. // (the creator's).
  3. //
  4. // WHERE THINGS ARE (one line per feature; README.md "Files" has the full list):
  5. // the login: email → code, limits per address / IP, the code page lib/login.hl (codes, IP buckets: lib/login-helpers.hl)
  6. // the account, its sessions, sign out everywhere, time zone lib/accounts.hl
  7. // identities, the short id, avatar lib/identities.hl (checks, label: lib/identities-helpers.hl)
  8. // apps, connections, the login button + exchange, an invite's login lib/apps.hl (checks, return URL: lib/apps-helpers.hl)
  9. // the identity selector (pick ids, the choice) lib/selector.hl (browser half: selector.js)
  10. // invites (ident#22) lib/invites.hl (checks: lib/invites-helpers.hl)
  11. // notifications: kinds, sending, inbox, per-app switches lib/notify.hl (checks, orders: lib/notify-helpers.hl)
  12. // mail (codes, invitations; IDENT_MAIL_SINK) lib/mail.hl
  13. // the function routes (/login, /api/*, /invite/:token, /code) lib/api.hl (plumbing: lib/api-helpers.hl, lib/jsoncheck.hl)
  14. // shared small helpers (storage dir, env, lists, text checks) lib/util.hl
  15. // pages: shell, sign-in + identities, start, apps, inbox, per-app components/*.hl; CSS components/styles.hl
  16. //
  17. // THE FLOWS (README "How apps use ident", "How apps send notifications", "Invites"):
  18. // GET /login?key=<api key>&return=<url> → error page, or → /signin/<rid> (sign in, choose the identity,
  19. // → <return url>?ident_code=<one-time code>)
  20. // POST /api/exchange { key, secret, code } → { identity } (the identity's short id only)
  21. // GET /selector.js, GET /api/selector/identities?key=, POST /api/selector/choose?key= {identity} → { code }
  22. // POST /api/code { email } → { email } | 400/429 { error } (a function route: the per-IP limit needs the request)
  23. // GET /code, /signin/<rid>/code the code form for this session's pending address, or → / resp. /signin/<rid>
  24. // Deploy (Byrodin): HL_HOST=127.0.0.1 binds loopback only (hl:web reads HL_HOST, hybriel#24),
  25. // IDENT_PORT the port.
  26. import WebFramework from 'hl:web'
  27. import { env } from 'hl:proc'
  28. import Styles from './components/styles.hl'
  29. import { dark, darker } from './shared/tokens.hl'
  30. import { appLogin, apiExchange, apiMigrateIds, apiCode, apiSelectorIdentities, apiSelectorChoose, apiInvites, apiInvitesList, apiInvitesGet, apiInvitesRevoke, inviteLink, apiKinds, apiNotify, apiOnline, notFoundApi, codePage } from './lib/api.hl'
  31. import Mail from './lib/mail.hl'
  32. import { sessionHooks, dropUserSessions } from './lib/accounts.hl'
  33. import { shortIdsBackfilled } from './lib/identities.hl'
  34. // ident#23: statics run on first use — touching it here gives every older identity its short id at boot
  35. console.log('ident: ' + shortIdsBackfilled + ' identities got their short id')
  36. import Home from './components/home.hl'
  37. import Start from './components/start.hl'
  38. import Apps from './components/apps.hl'
  39. import Inbox from './components/inbox.hl'
  40. import AppSettings from './components/appsettings.hl'
  41. static siteName = "ident"
  42. appTitle = siteName
  43. styles = Styles
  44. // ---- THE INSTALLABLE APP (mission 046, as calendar#3): hl:web generates the web app manifest
  45. // (/__hl/manifest.webmanifest, linked in every head with the apple-touch-icon and theme-color)
  46. // from these, and the service worker (/__hl/sw.js) from `offline`. No JavaScript of ours.
  47. // Icons: icons/ (icon.svg is the source, README "PWA"). Theme colour = the header's colour (token
  48. // `darker`), background `dark` — the same in every app (mission 046); the icon carries the accent.
  49. appThemeColor = darker.value
  50. appBackgroundColor = dark.value
  51. appFavicon = '/favicon.ico'
  52. appTouchIcon = '/icons/apple-touch-icon.png'
  53. appIcons = [
  54. { src = '/icons/icon-192.png' sizes = '192x192' purpose = 'any' }
  55. { src = '/icons/icon-512.png' sizes = '512x512' purpose = 'any' }
  56. { src = '/icons/icon-192.png' sizes = '192x192' purpose = 'maskable' }
  57. { src = '/icons/icon-512.png' sizes = '512x512' purpose = 'maskable' }
  58. ]
  59. // OFFLINE, WITHOUT PERSONAL DATA: the worker keeps only `/start` (components/start.hl, a page
  60. // with no data — never `/`, whose copy would hold the signed-in address and identities) and the
  61. // shell's assets. The installed app starts at `/start` (appManifest); online the shell's probe
  62. // (main.hl) sends it on to `/`, offline the header says it is offline. Every other page offline
  63. // is the worker's "Unavailable offline" (README "PWA").
  64. offline = [ Start ]
  65. appManifest = { start_url = '/start' }
  66. // ---- THE ROUTES: files, the function routes (lib/api.hl), the pages (components/) ----------------
  67. routes = [
  68. { pattern = "/favicon.ico" file = "./icons/favicon.ico" headers = { 'Cache-Control' = 'no-cache' } }
  69. { pattern = "/icons/icon-192.png" file = "./icons/icon-192.png" headers = { 'Cache-Control' = 'no-cache' } }
  70. { pattern = "/icons/icon-512.png" file = "./icons/icon-512.png" headers = { 'Cache-Control' = 'no-cache' } }
  71. { pattern = "/icons/apple-touch-icon.png" file = "./icons/apple-touch-icon.png" headers = { 'Cache-Control' = 'no-cache' } }
  72. { pattern = "/icons/icon.svg" file = "./icons/icon.svg" headers = { 'Cache-Control' = 'no-cache' } }
  73. { pattern = "/login" function = appLogin }
  74. { pattern = "/api/exchange" function = apiExchange }
  75. { pattern = "/api/migrate-ids" function = apiMigrateIds }
  76. { pattern = "/api/code" function = apiCode }
  77. { pattern = "/api/selector/identities" function = apiSelectorIdentities }
  78. { pattern = "/api/selector/choose" function = apiSelectorChoose }
  79. { pattern = "/api/invites" function = apiInvites }
  80. { pattern = "/api/invites/list" function = apiInvitesList }
  81. { pattern = "/api/invites/get" function = apiInvitesGet }
  82. { pattern = "/api/invites/revoke" function = apiInvitesRevoke }
  83. { pattern = "/invite/:token" function = inviteLink }
  84. { pattern = "/api/kinds" function = apiKinds }
  85. { pattern = "/api/notify" function = apiNotify }
  86. { pattern = "/selector.js" file = "./selector.js" headers = { 'Cache-Control' = 'no-cache' } }
  87. { pattern = "/avatar.js" file = "./avatar.js" headers = { 'Cache-Control' = 'no-cache' } }
  88. // the offline probe of the shell (components/main.hl): 204
  89. { pattern = "/api/online" function = apiOnline }
  90. { pattern = "/api/*" function = notFoundApi }
  91. // THE CODE PAGE (ident#20): renders Home through the framework's page render — it needs the server, BY REFERENCE
  92. { pattern = "/code" function = (route, req) => { return codePage(route, req, &server, Home) } }
  93. { pattern = "/signin/:rid/code" function = (route, req) => { return codePage(route, req, &server, Home) } }
  94. { pattern = "/" component = Home }
  95. { pattern = "/start" component = Start }
  96. { pattern = "/signin/:rid" component = Home }
  97. { pattern = "/apps" component = Apps }
  98. { pattern = "/inbox" component = Inbox }
  99. { pattern = "/inbox/:cid" component = AppSettings }
  100. ]
  101. // the mailer's result handlers live on an INSTANCE of lib/mail.hl
  102. mail = new Mail()
  103. sessionDir = env('IDENT_SESSIONS') != null ? env('IDENT_SESSIONS') : null
  104. port = env('IDENT_PORT') != null ? toNumber(env('IDENT_PORT')) : 8351
  105. // THE LISTENER's interface: hl:web reads HL_HOST (or HOST) itself (hybriel#24): 127.0.0.1 on
  106. // Byrodin behind nginx; unset = 0.0.0.0 (dev on Loreana).
  107. // IDENT_WATCH=0 turns the dev watcher off (the container: a deploy is an rsync + restart,
  108. // half-copied .hl files must not be re-analysed); unset = on, as before.
  109. watching = env('IDENT_WATCH') != '0'
  110. // WHO A PUSHED EVENT IS FOR: "signed out everywhere" reaches every open connection whose
  111. // session is the account's (checked before dropUserSessions clears the sessions).
  112. audience = {
  113. signedOutAll = (accountId, session) => { return session != null && session.user != null && session.user.id == accountId }
  114. }
  115. // ident's OWN COOKIE NAME. Cookies are per host, not per port: with the default `hlsid` an app
  116. // on the same host (tickets on :8350) and ident would overwrite each other's session cookie
  117. // → hl:web's `sessionCookie` setting (hybriel#10/#17).
  118. sessionCookie = 'identsid'
  119. server = new WebFramework(routes = routes, styles = styles, audience = audience, minify = true, port = port, watchMode = watching, sessionCookie = sessionCookie)
  120. // SIGN OUT EVERYWHERE deletes every session of the account (ticket #19, lib/accounts.hl dropUserSessions): the
  121. // session store is this server's
  122. sessionHooks.dropUser = (userId) => { return dropUserSessions(&server, userId) }

Branches

  • mainmain branch

Latest commits

  • 5fdbb6b2ident mission 009: report — scratch folder notemre
  • 74235815ident mission 009 (4/4): docs (README files map + same-output test, STATUS, LOG), report, tests/letcount.py + realdata-baseline/comparemre
  • fe183516ident mission 009 (3/4): let only where reassigned — 293 never-reassigned lets are plain declarations; kept: reassigned, loop bodies, names of a file member, a name declared twice in one function; same outputmre
  • d2e7f91bident mission 009 (2/4): one lib file per topic (login, accounts, identities, apps, invites, selector, notify + helpers, util), function routes as thin wrappers in lib/api.hl, project.hl = the map; same outputmre
  • 91017164ident mission 009 (1/4): file moves — the root .hl files into lib/ (api.hl → lib/api-helpers.hl), styles.hl → components/styles.hl; imports adjusted, no other changemre
  • f8bdcbc2ident: Hybriel master 06617221 (plugin allocators 3a781359 + 413f60e4, mpackdb 2cb7ae5e, http1 773de63e); all gates greenmre
  • ff78726cident: Hybriel master 190aa11d (fc838894 GC correctness, #127, #126 closure scopes); gates all greenmre
  • a3a7d21aident: Hybriel master 8efba065 (#126 GC by bytes, #48 lambda params copy); session-writing lambdas take &sessionmre
  • 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