openvibers/openvibe.space AGENTS.md
AGENTS.md
| 1 | # AGENTS.md — OpenVibe.Space |
| 2 | |
| 3 | ## Project overview |
| 4 | |
| 5 | OpenVibe.Space (`https://openvibe.space`) owns the network's static hosting and "spaces": small web |
| 6 | apps a person makes on their OpenVibe account, with a browser editor, an AI builder, templates, a |
| 7 | space SDK and a QuickJS sandbox for a space's own functions. It also serves tenant sites by Host |
| 8 | header at `<name>.openvibe.website` and on verified custom domains. |
| 9 | |
| 10 | - **Entry:** `server/index.js` (Express); app in `server/app.js`; port/service id `space`. |
| 11 | - **Hosting:** `server/artifacts/` (immutable content-addressed deploys, archive, path rules), |
| 12 | `server/http/upload.js`, `server/http/dashboard.js` (projects/sites/deploys/domains), |
| 13 | `server/http/tenant.js` (Host-header serving), `server/registry/` (resource index/control). |
| 14 | - **Spaces:** `server/spaces/` — `spaces.js`, `data.js`, `pages.js`, `render.js`, `sdk.js` |
| 15 | (the `/_openvibe/sdk.js` client), `ai.js`, `agent.js`, `templates.js`, `functions-worker.js` |
| 16 | (QuickJS WebAssembly sandbox), `content-check.js`, `guest.js`. |
| 17 | - **Pages:** `server/render/` (`website.js`, `hosting-pages.js`, `layout.js`, `pages.js`, |
| 18 | `short.js`); the editor is `public/js/space-editor.js`; public assets in `public/assets`, |
| 19 | `public/css`, `public/js`; manifest in `public/manifest.webmanifest`. No bundler. |
| 20 | - **Docs:** `docs/spaces.md` (the spaces model), `docs/cutover-pr-openvibe-space-43.md` (billing |
| 21 | readings cutover); deployment `deploy/nginx/openvibe.space.conf`, `openvibe.website.conf`. |
| 22 | |
| 23 | ## Owns, does not own |
| 24 | |
| 25 | Owns: spaces and their source files/settings, the gallery, editor, space SDK and API, shared lists |
| 26 | (`OV.items`), visitors' private storage (`OV.kv`), approved sign-ins and daily AI allowances; projects |
| 27 | and members, sites, immutable deploys, activation/rollback, previews, Git ingest, per-site |
| 28 | configuration, custom domains with TXT verification and takedowns; tenant serving; its `ov_space` |
| 29 | `space_*` tables, control log and outbox (`space.deploy.*`, `space.domain.verified`). |
| 30 | |
| 31 | Does not own: people, sessions or project identity (Network); stored bytes when |
| 32 | `SPACE_OBJECT_STORE=media` (Media); money and usage rating (Billing); the forum (Community); the |
| 33 | hosting price comparison (Host). The old forum URLs redirect to Community. |
| 34 | |
| 35 | ## Who calls it, what it calls |
| 36 | |
| 37 | People and their apps use the pages and the API; SDK `openvibe-sdk/space` is the client surface |
| 38 | (`deploys.uploadArchive/uploadFiles/uploadSourceBuild`, `sites.*`, `domains.*`, `projects.*`). |
| 39 | CI and Git ingest deploy through the same project-scoped app tokens. Space calls OpenVibe.Network |
| 40 | (identity, projects, JWKS), OpenVibe.AI (`space.app.build`, `space.app.ask`), OpenVibe.Media when |
| 41 | `SPACE_OBJECT_STORE=media` (`media.object.upload/read/list/delete` in the `space` namespace), |
| 42 | OpenVibe.Billing (`billing.usage.record` once `SPACE_BILLING_INTERVAL_MS` is on) and OpenVibe.Events |
| 43 | (the outbox when configured). `svc:space` needs `events.event.publish` and the Media grants above. |
| 44 | |
| 45 | ## Database and migrations |
| 46 | |
| 47 | PostgreSQL `ov_space` through `openvibe-sdk/db` (ADR-035): `migrations/0002_initial.sql` through |
| 48 | `0005_git_sources.sql` create the hosting tables with Host Stage B's `space_` names; `0006` the |
| 49 | billing-readings outbox; `0008` telemetry; `0009` the spaces tables (`space_apps`, |
| 50 | `space_app_files`, `space_app_projects`, `space_app_items`, `space_app_kv`, `space_app_grants`, |
| 51 | `space_app_codes`, `space_app_tokens`, `space_app_counters`); `0010` account data. `0001` is the |
| 52 | historical forum schema and is not dropped. Migrations run at boot; tables are never created by a |
| 53 | request. Only hashes of sign-in codes and tokens are stored. |
| 54 | |
| 55 | ## Auth and exposure |
| 56 | |
| 57 | Network SSO and JWTs. APIs ignore cookies; a person's session is the pages' auth and the API uses |
| 58 | bearer tokens. A space's visitor approves a sign-in once and Space keeps only the code/token hash. |
| 59 | Static uploads are validated before storage; tenant content runs on a separate registrable domain and |
| 60 | previews use a sandbox CSP. `/_openvibe/sdk.js` is the space SDK; function code runs in the QuickJS |
| 61 | sandbox at `/api/<name>` and from `OV.fn`. `/internal/events` is HMAC-verified and loopback-only. |
| 62 | |
| 63 | **Public hosting is off by default** (`SPACE_PUBLIC_HOSTING=off`): only OpenVibe staff can create |
| 64 | projects. Abuse handling and a designated DMCA agent precede public launch — do not flip the switch |
| 65 | in a normal change. |
| 66 | |
| 67 | ## Deploy |
| 68 | |
| 69 | `sudo ovhost deploy space`: release layout under `/opt/openvibe.space`, env `/etc/openvibe/space.env`, |
| 70 | unit `openvibe-space`, migrations at boot; rollback with `sudo ovhost rollback space --to <sha>`. |
| 71 | Vhosts live in `deploy/nginx/` (installed with `ov-vhost-install`). The `.gitignore` keeps |
| 72 | `node_modules`, data and keys out of the repository. |
| 73 | |
| 74 | ## Commands and tests |
| 75 | |
| 76 | ```bash |
| 77 | npm ci |
| 78 | npm run dev # http://127.0.0.1:4940 |
| 79 | npm test # every test/*.test.js, in-process Network/Media/Chat/VIP mocks |
| 80 | npm test -- spaces deploy # only matching files |
| 81 | npm run test:pg # the same on the PostgreSQL containers |
| 82 | ``` |
| 83 | |
| 84 | `test/run.js` uses `openvibe-shared/test-runner` (60 s, serial); tests boot mocks and a temp database, |
| 85 | never the network. They cover upload validation and immutable deploys, activation/rollback, the |
| 86 | Host-header tenant and custom domains, site config/CSP, spaces (files, lists, kv, sign-ins, sandbox |
| 87 | functions, AI calls, templates), project export/deletion, the outbox and telemetry. `VERBOSE=1` is |
| 88 | not wired here; use `npm test -- <word>`. |
| 89 | |
| 90 | ## Conventions and pitfalls |
| 91 | |
| 92 | - CommonJS, 4-space indent, single quotes, semicolons; problem+json for API errors and escaped, |
| 93 | server-rendered HTML for pages. No framework and no build step. |
| 94 | - **Deploys are immutable and content-addressed.** Never overwrite an artifact; activation and |
| 95 | rollback point a site at a deploy, and `deploy/*` rows are an audit trail. |
| 96 | - **Tenant isolation:** a tenant site is served only by Host header and never through the |
| 97 | first-party cookie; previews use the sandbox CSP. Do not add a route that mixes origins. |
| 98 | - **A space's server code is untrusted:** it runs in the QuickJS sandbox with the space's grants; |
| 99 | never eval it in Node and never give it the service token. |
| 100 | - **Limits and allowances are per space/person per day** (`server/spaces/ai.js`); a new AI call needs |
| 101 | the same accounting. |
| 102 | - **The forum is gone from here:** old forum URLs redirect to Community; do not revive the `0001` |
| 103 | tables or add endpoints against them. |
| 104 | - New environment variables go into `.env.example` and the README; values live only in |
| 105 | `/etc/openvibe/space.env`. |
| 106 |