openvibers/openvibe.computer AGENTS.md

AGENTS.md

main 7.0 KB · 126 lines · markdown

1# AGENTS.md — OpenVibe.Computer
2
3## Project overview
4
5The front door and API facade for OpenVibe computers: a public site that renders the product, signs a
6person in through OpenVibe.Network SSO, and forwards that person's Network token **unchanged** to
7OpenVibe.Run. Run owns sessions, placement, budgets and the actual computer; Computer owns no
8sessions and stores nothing.
9
10- Origin `https://openvibe.computer`, port `5135`, unit `openvibe-computer.service`,
11 release root `/opt/openvibe.computer`.
12- Node.js/Express, CommonJS, **no database, no migrations, no build step**; server-rendered pages.
13
14## What it owns
15
16- The public pages: `/`, `/templates`, `/pricing`, `/docs`, `/updates`, legal pages.
17- `/api/v1/computers` and `/api/v1/computers/{id}[/stop|/screenshot|/act|/handoff]` — a thin facade
18 that calls Run with the caller's own bearer token.
19- `/auth/*` — the Network OAuth client `computer` (callback `/auth/callback`), the session cookie and
20 optional auth for pages.
21- `/llms.txt`, `/llms-full.txt`, `/sitemap.xml`, `/robots.txt`, `/openapi.json`,
22 `/.well-known/agent.json`, `/release.json`, `/shared/*`, `/api/health`.
23
24It does not own: the computer, the browser, placement, the allowance, per-minute pricing, the
25session budget, screenshots or control handoff. Those are Run's. The UI marks what Run does not yet
26expose as **pending**, and that must stay honest.
27
28## Who it calls, and who calls it
29
30- **OpenVibe.Run** — every session action goes through [server/run-client.js](server/run-client.js) to
31 `OV_RUN_URL` (`/api/v1/sessions…`, `/commands`, `/control`, `/timeline`, `/snapshot`). The person's
32 Network token is passed through as `Authorization: Bearer`; Computer never mints or broadens one.
33- **OpenVibe.Network** — SSO through `openvibe-sdk/sso` (`createSsoClient`), OAuth client `computer`.
34- Called by people in the browser and by agents that read the public pages/OpenAPI. There is no
35 service-to-service caller and no contract of its own.
36
37## Repository map
38
39- **Entry:** [server/index.js](server/index.js) — `createApp()`, listen on `config.port`/`config.host`.
40- **App:** [server/app.js](server/app.js) — helmet CSP, SSO router + optional auth, health, robots,
41 sitemap, legal, llms files, openapi, agent descriptor, `/api/v1`, release, `/shared`, static,
42 pages, error handler.
43- **Config:** [server/config.js](server/config.js) — env load (`PORT`, `BASE_URL`, `OV_RUN_URL`,
44 `OV_OAUTH_CLIENT_ID/SECRET`, `OV_NETWORK_*`, secure cookies).
45- **Run client:** [server/run-client.js](server/run-client.js) — `RunError`, `list/get/create/stop/
46 command/control/take/timeline/snapshot`; creates browser sessions only.
47- **API:** [server/api.js](server/api.js) — token extraction, RFC 9457 problem+json errors, the routes.
48- **Pages:** [server/pages.js](server/pages.js), [server/layout.js](server/layout.js),
49 [server/html.js](server/html.js), [server/product.js](server/product.js).
50- **Deploy:** [deploy/systemd/openvibe-computer.service](deploy/systemd/openvibe-computer.service),
51 [deploy/nginx/openvibe.computer.conf](deploy/nginx/openvibe.computer.conf),
52 [deploy/LAUNCH.md](deploy/LAUNCH.md) (DNS, TLS, OAuth, service add, vhost swap).
53- **Static:** [public/openapi.json](public/openapi.json), [public/llms.txt](public/llms.txt),
54 [public/.well-known/agent.json](public/.well-known/agent.json), [public/css/computer.css](public/css/computer.css).
55
56## Commands
57
58```bash
59npm ci
60cp .env.example .env # if present; the README lists the variables
61npm run dev # NODE_ENV=development node server/index.js
62npm start # node server/index.js, http://127.0.0.1:5135
63npm test # node --test test/*.test.js
64ov test # the harness's sharded run of what the change reaches
65node --check <file.js>
66```
67
68## Auth
69
70`openvibe-sdk/sso` owns the OAuth flow and cookie (`createSsoClient({ site: 'computer', … })`).
71Pages use `sso.optionalAuth()`; API routes take the bearer token with `sso.extractToken(req)` and
72answer `401 application/problem+json` (`computer.auth.required`) when it is absent. Run authorizes
73the token and its budget — Computer does not decide entitlement. `OV_OAUTH_CLIENT_SECRET` is required
74for sign-in; without it the flow cannot complete.
75
76## Frontend loading model
77
78Server-rendered HTML from `server/pages.js`/`server/layout.js` and `server/html.js`; no SPA, no
79bundler, no transpiler. Static files are served from `public/`; shared frame assets come from the
80pinned `openvibe-shared` tarball through `/shared/*` (`openvibe-shared/serve`). The CSP in
81[server/app.js](server/app.js) is the real allow-list (Network, Chat, Billing, Events, Media,
82Cloudflare insights, self) — add an origin there before using it.
83
84## Deploy
85
86`sudo ovhost service add computer` (once) then `sudo ovhost deploy computer --restart`
87([deploy/LAUNCH.md](deploy/LAUNCH.md)). Unit `openvibe-computer.service`, env
88`/etc/openvibe/computer.env` (0600), vhost installed with `sudo ovhost nginx render computer --install`.
89The launch is a host-level swap: the `openvibe.computer` parked redirect is removed **only after**
90review and readiness, in the same change that installs the vhost. Do not remove the redirect in a
91service PR. Health check: `http://127.0.0.1:5135/api/health`.
92
93## Tests
94
95`npm test` is Node's built-in runner over [test/computer.test.js](test/computer.test.js) and
96[test/link-brand.test.js](test/link-brand.test.js). They pin the facade contract: 401 without a
97token, browser-only creation, the three templates, Run errors mapped to problem+json, the public
98pages/llms/sitemap, the brand rules and the CSP. `ov test` runs the same suite.
99
100## Conventions
101
102- CommonJS, 4-space indent, single quotes, semicolons; `server/` modules export factories
103 (`createApp`, `createApi`, `createPages`) so tests inject config/SSO/Run.
104- Public-facing copy is calm and specific; no unverified capability claims ("pending" stays pending).
105- Error bodies follow RFC 9457 (`application/problem+json`) with a stable `code`.
106- DNS/TLS/OAuth/vhost steps belong in [deploy/LAUNCH.md](deploy/LAUNCH.md), not in code.
107
108## Pitfalls
109
110- **Computer is a facade.** Do not add session state, a database, billing logic or placement here;
111 that belongs in Run.
112- **Never mint or rewrite the forwarded token.** Pass the person's own token through.
113- **The parked redirect is intentional** until the review in `deploy/LAUNCH.md`; removing it early
114 sends the domain to a service that may not be live.
115- **CSP is enforced.** A new script/font/frame origin must be added to the helmet directives or it
116 will be blocked; do not add `unsafe-eval`.
117- **Run support is partial.** Desktop/GPU/always-on, live streams, B3 control modes, control handoff
118 timelines, snapshots and non-browser kinds are not available yet; the UI says so.
119- **No build step:** a change to `public/` or the view strings is live on the next deploy/restart.
120
121## Documentation
122
123- [README.md](README.md) — product summary and the current Run support.
124- [deploy/LAUNCH.md](deploy/LAUNCH.md) — the host-level launch sequence.
125- [public/openapi.json](public/openapi.json) — the API surface served to clients.
126