gitoriaLog in with ident

gitoria

All repositories: gitoria

ReadmeCodePull requestsReleasesTicketsSettings
Commit110c2799110c2799mission 002 (code order) 1/4: .hl files out of the root — lib/ (api, git, localtime, markdown, repos, sshgate, sshkeys, tickets, tokens, transport, users), components/styles.hl; jsoncheck.hl removed (imported nowhere); import paths only. gates 200/0, 46/0, 44/0; real-data reads + writes identicalmre110c2799/tests/ticketskit.mjs

3.9 KB

  1. // tests/ticketskit.mjs — a throw-away tickets.worldapi.org for the gate (ticket gitoria#10): tickets' code
  2. // COPIED without .env / storage / sessions (never the live one, never its data), started on its own port and
  3. // storage, logged in through the gate's ident, with an API token for the tickets user "gitoria".
  4. // const t = await startTickets({ ticketsDir, workDir, port, ident, identAlice }) // → { base, token, stop(), api(path) }
  5. import { spawn } from 'node:child_process';
  6. import { cpSync, mkdirSync, rmSync, existsSync } from 'node:fs';
  7. import { join } from 'node:path';
  8. const sleep = (ms) => new Promise(r => setTimeout(r, ms));
  9. const J = JSON.stringify;
  10. const SKIP = new Set(['.env', 'storage', '.sessions', '.scratch', 'server.log', 'server.pid', 'testapp', '.git', 'tests', 'import']);
  11. export async function startTickets({ ticketsDir, workDir, port, ident, who, origins = '' }) {
  12. const code = join(workDir, 'tickets-code');
  13. const data = join(workDir, 'tickets-data');
  14. rmSync(workDir, { recursive: true, force: true });
  15. mkdirSync(code, { recursive: true });
  16. mkdirSync(data, { recursive: true });
  17. cpSync(ticketsDir, code, { recursive: true, filter: (src) => {
  18. const rel = src.slice(ticketsDir.length).replace(/^\/+/, '');
  19. return rel === '' || !SKIP.has(rel.split('/')[0]);
  20. } });
  21. if (existsSync(join(code, '.env'))) throw new Error('ticketskit: a .env was copied — refusing to start');
  22. const base = `http://127.0.0.1:${port}`;
  23. const app = await ident.registerApp(who, 'tickets (gitoria gate)', [base]);
  24. let log = '';
  25. const proc = spawn(join(code, 'bin/hybriel'), ['project.hl'], {
  26. cwd: code,
  27. env: { ...process.env, TICKETS_PORT: String(port), TICKETS_STORAGE: join(data, 'mpackdb'), TICKETS_SESSIONS: join(data, 'sessions') + '/', TICKETS_WATCH: '0',
  28. HL_HOST: '127.0.0.1', IDENT_URL: ident.base, IDENT_EXCHANGE_URL: ident.base, TICKETS_PUBLIC_URL: base, IDENT_API_KEY: app.key, IDENT_API_SECRET: app.secret, TICKETS_CREATOR_IDENTITY: '', TICKETS_CONNECT_ORIGINS: origins },
  29. stdio: ['ignore', 'pipe', 'pipe'],
  30. });
  31. proc.stdout.on('data', d => log += d); proc.stderr.on('data', d => log += d);
  32. let up = false;
  33. for (let i = 0; i < 80 && !up; i++) { try { up = (await fetch(base + '/api/projects')).ok; } catch {} if (!up) await sleep(250); }
  34. if (!up) throw new Error('tickets did not come up\n' + log);
  35. // the user "gitoria": the login button's server half, a display name, an API token
  36. const first = await fetch(base + '/');
  37. const cookie = (first.headers.get('set-cookie') || '').split(';')[0];
  38. const cb = await fetch(base + '/login/callback?ident_code=' + await ident.selectorCode(who, app, base), { headers: { cookie }, redirect: 'manual' });
  39. if (cb.status !== 302) throw new Error('tickets login failed: ' + cb.status);
  40. let n = 0;
  41. const emit = async (event, payload) => {
  42. const r = await fetch(base + '/__hl/emit', { method: 'POST', headers: { 'content-type': 'application/json', cookie }, body: J({ t: 'emit', i: ++n, event, payload }) });
  43. const t = await r.text(); let j = null; try { j = JSON.parse(t); } catch {}
  44. return { raw: t, value: j && j.value };
  45. };
  46. const nm = await emit('saveDisplayName', ['gitoria']);
  47. if (!nm.value || nm.value.name !== 'gitoria') throw new Error('tickets name failed: ' + nm.raw);
  48. const tk = await emit('tokenCreate', ['gitoria gate']);
  49. const token = tk.value && tk.value.token;
  50. if (!/^tkt_[0-9a-f]{48}$/.test(token || '')) throw new Error('tickets token failed: ' + tk.raw);
  51. return {
  52. base, token, cookie, log: () => log,
  53. async api(path, headers = {}) { const r = await fetch(base + path, { headers }); const t = await r.text(); let j = null; try { j = JSON.parse(t); } catch {} return { status: r.status, json: j }; },
  54. async stop() {
  55. try { proc.kill('SIGTERM'); } catch {}
  56. await new Promise(r => { if (proc.exitCode !== null || proc.signalCode !== null) return r(); proc.once('exit', r); setTimeout(r, 3000); });
  57. },
  58. };
  59. }

Branches

Latest commits

  • 110c2799mission 002 (code order) 1/4: .hl files out of the root — lib/ (api, git, localtime, markdown, repos, sshgate, sshkeys, tickets, tokens, transport, users), components/styles.hl; jsoncheck.hl removed (imported nowhere); import paths only. gates 200/0, 46/0, 44/0; real-data reads + writes identicalmre
  • fdfb4b1bgitoria: Hybriel master 06617221 (plugin allocators 3a781359 + 413f60e4, mpackdb 2cb7ae5e, http1 773de63e); gates 200/0, 46/0, 44/0mre
  • 5b46ac84antcolony#40: LOG.md — missions 069/072 are antcolony missions (report paths on Byrodin)mre
  • 5602ff41gitoria: Hybriel master 190aa11d (fc838894 GC correctness, #127 mountKids by reference, #126, #48) — tracker README flat; gates 200/0, 46/0, 44/0mre
  • e85eaf01gitoria: 069 round 2 — hybriel 1a096ad3 not adopted (Markdown SSR still grows); browser gate waits for the server-side logout before restartmre
  • 09ce4f3fgitoria: mission 069 re-vendor hybriel 8efba065 stopped (big SSR pages grow + slow down); lambda audit clean; old vendor keptmre
  • 3dc43108antcolony#40: mission references point to the moved missionsmre
  • 8d9450fdantcolony#40: history (LOG.md), worker briefs (missions/) and reports moved here from antcolony, numbered per project; old numbers in antcolony docs/mission-map.mdmre
  • 205d5fe4gitoria: Hybriel master ff51cf46; ssh keys/tokens no double rows (session sync); gates follow #20mre
  • 9b27cb26gitoria#21: installable app (manifest, service worker, offline start page), own iconmre
  • 68dcb603deploy.sh: back up live storage/.sessions/.env before every deploy (newest 5 kept)mre
  • e2deed6dgitoria#20: "Add code" only on the Code page of an empty repository, no collapsiblemre
  • 8bb97ffddeploy.sh: never send .git or .gitignore to Byrodinmre
  • fd981932State of 2026-09-27; bin/ no longer tracked (Hybriel commit is in README)mre
  • 4a2d7125initial commitmre