gitoriaLog in with ident

ident

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commitfe183516fe183516ident 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 outputmrefe183516/lib/selector.hl

2.8 KB

  1. // lib/selector.hl — THE IDENTITY SELECTOR (piece 3 of 6, ticket #26; CONCEPT.md "Flow 2: identity selector"
  2. // and "Decided 2026-09-24"). Statics only, the server realm. Its two CORS endpoints are lib/api.hl
  3. // (apiSelectorIdentities, apiSelectorChoose; the CORS answers and the caller check: lib/api-helpers.hl);
  4. // the browser half is selector.js (served at /selector.js).
  5. //
  6. // GET /api/selector/identities?key=<api key> → { signedIn, identities: [{ id, name }] }
  7. // POST /api/selector/choose?key=<api key> { identity: <id from the list> } → { code }
  8. // OPTIONS /api/selector/choose?key=… the CORS preflight of the POST
  9. //
  10. // CORS: ident answers ONLY a request whose Origin header is one of the app's registered
  11. // origins AND whose key is that app's API key. Then (and only then) the answer carries
  12. // `Access-Control-Allow-Origin: <that exact origin>` and `…-Allow-Credentials: true`
  13. // (never `*`). Anything else is a 403 without those headers: the browser hands the page
  14. // nothing, and nothing is written.
  15. // The ident user is the one of the `identsid` cookie the browser sends along (credentials;
  16. // SameSite=Lax, so it only travels from the SAME SITE — our apps; other ports of the same
  17. // host count). Function routes get no session: it is resolved from the cookie (hybriel #18).
  18. //
  19. // THE LIST'S ids are not ident's identity ids: each is sha256(app's secret hash : identity)
  20. // cut to 32 hex — stable for one app, different for every app, not guessable, and it
  21. // means nothing outside this selector. The CODE of a choice follows the login button's
  22. // rules exactly (lib/apps.hl issueCode: single use, 60 s, this app only); the host's server
  23. // trades it with POST /api/exchange (key + secret) for the app-specific identity id.
  24. import { sha256 } from 'hl:crypto'
  25. import { issueCode } from './apps.hl'
  26. import { identityRecords } from './identities.hl'
  27. import { labelOf } from './identities-helpers.hl'
  28. // (since mission 009 the identity's id is its UUID, so every pick id changed once then)
  29. static pickOf = (appRec, identityRec) => { return sha256(appRec.secretHash + ':' + identityRec.id).slice(0, 32) }
  30. // the account's identities for the app's page: the id to pick it by and the identity
  31. // name (CONCEPT.md: "that one is shown in the selector"; blank → the list's fallback)
  32. static selectorList = (appRec, accountId) => {
  33. out = []
  34. let n = 1
  35. for (r of identityRecords(accountId)) {
  36. out.push({ id = pickOf(appRec, r) name = labelOf(r, n) })
  37. n = n + 1
  38. }
  39. return out
  40. }
  41. // THE CHOICE: the account's identity whose pick id is `pick` gets a one-time code for the app. Answers the
  42. // code, or null (no such identity).
  43. static codeOfPick = (appRec, accountId, pick) => {
  44. for (r of identityRecords(accountId)) {
  45. if (pickOf(appRec, r) == pick) {
  46. return issueCode(appRec.id, r.id)
  47. }
  48. }
  49. return null
  50. }

Branches

Latest commits

  • 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