Mirror of github.com/OpenVibers/OpenVibe.Space
  • JavaScript 88.5%
  • CSS 3.9%
  • PLpgSQL 3.8%
  • HTML 3.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
OpenVibers 4b51c37e07
openvibe-contracts v0.216.0 (was v0.215.0) (#97)
Opened by scripts/pin-bump.js in OpenVibers/OpenVibe.Shared after the v0.216.0 release.
2026-10-27 04:59:53 -07:00
.github/workflows Space: the forum moves back to Community; Space becomes code hosting and spaces (coming) (#9) 2026-10-08 16:19:36 -07:00
deploy Space: the tenant vhost's function location quotes its regex (nginx reads an unquoted {0,39} as a block) (#63) 2026-10-16 14:14:55 -07:00
docs Space functions: export/export default/module.exports handlers work (the AI builder wrote export async function handle), always run as a script, and an error names its line (#64) 2026-10-16 14:25:39 -07:00
migrations Space: account export and deletion again (ADR-033, openvibe-sdk/account-data): a person's spaces with their files, their list items, private storage and sign-ins; deletion closes their published spaces and removes their data from everyone's (#59) 2026-10-16 13:15:03 -07:00
public Phones: list grids size their columns with minmax(0, 1fr) (or a min(…, 100%) minimum), so one long line can never widen a page past the screen (#86) 2026-10-25 03:36:41 -07:00
server /auth/me is not counted by the sign-in limiter: 60 page views in 15 minutes made a signed-in visitor look signed out (#93) 2026-10-26 22:15:21 -07:00
templates/spaces Spaces: server functions (functions/<name>.js) run in a QuickJS sandbox at /api/<name>, from OV.fn and in the editor's preview, with a Trivia starter whose answers stay on the server (#62) 2026-10-16 14:11:39 -07:00
test openvibe-shared v4.13.0 (was v4.12.0) (#87) 2026-10-25 18:09:48 -07:00
.env.example Space: account export and deletion again (ADR-033, openvibe-sdk/account-data): a person's spaces with their files, their list items, private storage and sign-ins; deletion closes their published spaces and removes their data from everyone's (#59) 2026-10-16 13:15:03 -07:00
.gitignore OpenVibe.Space: the forum moves off OpenVibe.Community (plan T10 step 3) (#1) 2026-10-07 11:51:36 -07:00
.gitleaks.toml Space: static hosting moves here from Host (space.* contracts, staff-only), with a dashboard design pass (#36) 2026-10-12 03:46:53 -07:00
CHANGELOG.md Emit daily gb-month storage readings to Billing in local store mode (#43) 2026-10-14 10:03:25 -07:00
LICENSE OpenVibe.Space: the forum moves off OpenVibe.Community (plan T10 step 3) (#1) 2026-10-07 11:51:36 -07:00
package-lock.json openvibe-contracts v0.216.0 (was v0.215.0) (#97) 2026-10-27 04:59:53 -07:00
package.json openvibe-contracts v0.216.0 (was v0.215.0) (#97) 2026-10-27 04:59:53 -07:00
README.md openvibe-contracts v0.216.0 (was v0.215.0) (#97) 2026-10-27 04:59:53 -07:00
SECURITY.md OpenVibe.Space: the forum moves off OpenVibe.Community (plan T10 step 3) (#1) 2026-10-07 11:51:36 -07:00
STATUS.json openvibe-contracts v0.216.0 (was v0.215.0) (#97) 2026-10-27 04:59:53 -07:00

OpenVibe.Space

https://openvibe.space — spaces (apps people make on their OpenVibe account) and static hosting for the OpenVibe network.

Purpose and status

Space owns static hosting. The Stage B engine moved here from OpenVibe.Host as code; production had no projects, sites or deploys to migrate. It supports projects and members, immutable content-addressed deploys, activation and one-step rollback, private previews, CI Git ingest, per-site configuration, verified custom domains, takedowns, Media-backed objects, Host-header tenant serving, and a resource index. Tenant names serve at <name>.openvibe.website.

Public hosting remains off by default (SPACE_PUBLIC_HOSTING=off). Only OpenVibe staff can create projects. Abuse handling and a designated DMCA agent precede public launch.

Spaces (plan T20 step 2; server/spaces/, docs/spaces.md) are small web apps people make here: described to the AI builder (OpenVibe.AI space.app.build), started from a template (guestbook, AI buddy, poll, reaction game, trivia, private to-dos, blank) or forked, then edited in a browser editor with a live preview. A space uses the visitor's OpenVibe account through the space SDK (/_openvibe/sdk.js): sign-in that the visitor approves once, shared lists (OV.items), private storage (OV.kv), the space's own AI (OV.ai.ask, OpenVibe.AI space.app.ask on behalf of the visitor) and its own server code (functions/<name>.js, run in a QuickJS WebAssembly sandbox at /api/<name> and from OV.fn). Making, editing, previewing and the AI builder work for everyone signed in. Publishing deploys a space to a site of its maker's Spaces project at <slug>.openvibe.website, so it follows the same launch switch: staff until SPACE_PUBLIC_HOSTING=on.

OpenVibe.Host is the hosting price comparison; its copy of the engine is being removed, and its old hosting URLs will answer 410 with a link here.

Owns

  • Spaces: their source files and settings, the gallery, the editor, the space SDK and its API, each space's shared lists, its visitors' private storage, the sign-ins visitors approved, and the daily AI allowances of spaces and builders.
  • Static hosting: projects and members, sites, immutable content-addressed deploys, activation and rollback, previews, Git ingest, per-site configuration, custom domains with TXT verification, and takedowns.
  • Serving tenant sites by Host header at <name>.openvibe.website and on verified custom domains.
  • Its tables in ov_space (space_*), its control log and its outbox (space.deploy.*, space.domain.verified).

Does not own

  • People, sessions and projects' identity (OpenVibe.Network), stored bytes when SPACE_OBJECT_STORE=media (OpenVibe.Media), money and usage rating (OpenVibe.Billing), the forum (OpenVibe.Community, see below) and the hosting price comparison (OpenVibe.Host).

Depends on

  • OpenVibe.Network: sign-in (OAuth with PKCE), tokens and their keys, project membership.
  • OpenVibe.Events: the outbox relay, when EVENTS_URL is set, and account export and deletion (ADR-033): network.account.export_requested and network.account.deleted reach the loopback /internal/events consumer (server/account-data.js, openvibe-sdk/account-data), signed with SPACE_EVENTS_SECRET. A person's spaces are exported with their files; on deletion their published spaces stop serving and the spaces go with what others kept in them, and their list items, private storage and sign-ins leave other people's spaces.
  • OpenVibe.Media: tenant objects, when SPACE_OBJECT_STORE=media.
  • OpenVibe.Billing: storage readings, when SPACE_BILLING_INTERVAL_MS is on.
  • OpenVibe.Services: reads the resource index and sends control requests.
  • OpenVibe.AI: the space builder and a space's own AI (space.* workflows; Network grants ai.run.create and ai.run.read on space.*).

The forum moved to OpenVibe.Community

The forum lived here from 3 October 2026 (it moved off Community then). On 2026-10-08 the owner moved it back: OpenVibe.Community owns the forum (spaces, threads, posts, votes, categories, per-space moderators, the Discord relay) again, and Space became the network's hosting (static sites now; dynamic pages and spaces next).

So Space keeps no forum code and every forum URL answers a permanent redirect to the same path and query on https://openvibe.community:

Path Methods Status
/s, /s/* (pages, feeds) GET, HEAD 301
/s, /s/* anything else 308 (the method and body are preserved)
/api/v1/spaces*, /api/v1/posts/*, /api/v1/space-groups*, /api/v1/relay* all 308

A redirected bookmark, crawler or API client therefore lands on Community's copy of the same page. Nothing that is not a forum path redirects.

Routes

Route Purpose
/ Spaces and static hosting
/spaces, /spaces/new, /spaces/mine, /spaces/:slug The gallery and templates, making a space (template or AI builder), your spaces, a space's page
/spaces/:slug/edit and its JSON calls (files, settings, ai, publish, unpublish, delete, preview) The editor (maker or staff; same origin with the form token in X-CSRF-Token)
/spaces/:slug/fork, /spaces/:slug/connect Fork a space; the sign-in a visitor approves for a published space
/_openvibe/sdk.js The space SDK: live on a space's own address, preview mode on openvibe.space
/api/v1/apps/:id/token, /api/v1/apps/:id/run, /api/v1/apps/:id/items/:collection The space SDK's API, from the space's own origin only (CORS for that origin, Bearer space token, never cookies)
/dashboard, /projects/:id, /sites/:id, /deploys/:id Signed-in hosting dashboard and forms
/preview/:deployId/* Private, sandboxed deploy preview
/api/v1/projects, /api/v1/sites, /api/v1/deploys, /api/v1/domains Hosting API (Bearer tokens, no cookie auth)
/api/v1/resources First-party resource index
POST /api/v1/resources/control First-party control: delete a site, deploy or domain for a person (Space's own roles decide)
/limits.json Enforced hosting limits
`/auth/login callback
/robots.txt, /llms.txt, /llms-full.txt, /sitemap.xml Discovery for Space's public page
/api/health, /api/ready, /release.json, /metrics Health, release and observability

Sitemap entries carry lastmod from the release commit or, for hosted pages, the active deploy.

Tenant requests are dispatched by Host header before dashboard routes. deploy/nginx/openvibe.website.conf is a reference wildcard vhost; the existing openvibe.space vhost includes larger upload locations. Neither is installed by this code change. Unknown hosts answer 404. Tenant sites cannot reach the dashboard, API, auth or metrics. A custom domain serves only after TXT verification.

Capabilities and events

The hosting API guards space.site.manage, space.site.config, space.deploy.create, space.domain.manage, space.resource.read and space.resource.control (openvibe-contracts 0.170.0, owner space); every route names exactly one, and npx openvibe-contracts-check --service space checks the code against the release. Service tokens need audience openvibe.space, and project membership still applies. The per-actor limits (server/http/actor-limits.js) count uploads, domain checks, project creation and writes per person or app; those are limit buckets, not capabilities. The retired space.forum.* contracts are unrelated to hosting. The control route (server/registry/resource-control.js, plan T13 step 10) takes a common.resource-control-request@1 from OpenVibe.Services and acts as the person in on_behalf_of through the same domain code as the DELETE routes: deleting needs maintainer or owner, a non-member gets resources.unknown_resource, and the served deploy (deploy.active), a default domain (domain.default) and anything taken down are refused with Space's own reason. Dry runs; repeats with the same key return the first answer (space_control_log).

The transactional outbox emits space.deploy.created, space.deploy.activated, space.deploy.failed and space.domain.verified; each has a payload schema in openvibe-contracts, and the SDK outbox refuses any other type.

Data and configuration

migrations/0002_initial.sql through 0005_git_sources.sql create the hosting tables, 0006_billing_readings.sql the usage-reading outbox,, indexes and immutable-artifact triggers from Host Stage B with space_ names. They run through openvibe-sdk/db at boot; tables are never created by a request. 0001_initial.sql remains the historical forum schema, which this release does not drop. This is a code move, with no data copy.

migrations/0009_spaces.sql creates the spaces tables (space_apps, space_app_files, space_app_projects, space_app_items, space_app_kv, space_app_grants, space_app_codes, space_app_tokens, space_app_counters). Only hashes of sign-in codes and tokens are kept. migrations/0010_account_data.sql creates openvibe-sdk/account-data's account_data_events (the forum-era table of that name is kept as account_data_events_forum).

Request telemetry is aggregated by route template, method and status class, never by raw URL. Once a minute one http.request sample per key, plus the active-requests, p95 latency and event-loop-lag gauges, is written to this service's own telemetry_samples table (openvibe-sdk 0.46 telemetry, the platform.telemetry-sample@1 shape), which migrations/0008_telemetry.sql creates; rows older than 14 days are deleted daily. /shared files, static assets, health, readiness and /metrics are not counted. server/app.js mounts openvibe-sdk's telemetryMiddleware (a no-op until init); server/index.js calls telemetry.init() at production start, runs the 14-day retention and flushes on stop.

Copy .env.example to .env. Production uses /etc/openvibe/space.env (0600). Important values:

Variable Default Purpose
SPACE_PUBLIC_HOSTING off Staff-only project creation (and publishing spaces) until launch
SPACE_EVENTS_SECRET unset Signs OpenVibe.Events deliveries to /internal/events (account export and deletion); unset answers 503
SPACE_AI, OV_AI_INTERNAL_URL on, http://127.0.0.1:4700 The space builder and spaces' AI through OpenVibe.AI
SPACE_SPACES_PER_OWNER, SPACE_AI_BUILDS_PER_DAY, SPACE_AI_ASKS_PER_SPACE_PER_DAY 25, 20, 500 Spaces per person, AI builds per person a day, AI answers per space a day (more SPACE_SPACE_* limits in server/hosting-config.js)
SPACE_SITES_DOMAIN openvibe.website Tenant names
SPACE_STORAGE_DIR ./data/objects Content-addressed local object store
SPACE_OBJECT_STORE local Set media for Media write-through and cache
SPACE_FORM_SECRET random per process Dashboard CSRF form signing
SPACE_WORKER on Domain rechecks, object sweep, outbox pruning
EVENTS_URL unset Outbox relay destination; unset keeps rows queued
SPACE_BILLING_INTERVAL_MS 0 (off) Daily gb-month storage readings to OpenVibe.Billing (OV_BILLING_URL) in local mode, per OpenVibe.Network project (network_project_id; a project that names none gets no reading); Media mode emits none (Media bills the bytes)
DATABASE_URL, DATABASE_DIRECT_URL unset PostgreSQL serving and owner migration connections

Other SPACE_* quota, upload, domain and DNS settings are listed in .env.example and server/hosting-config.js. Space keeps its existing OAuth and forum redirect settings.

Tests and running

npm install
npm start
npm test

test/hosting-core.test.js exercises migrations, launch gate, project/site creation, tenant dispatch, immutable deploys, pointer rollback and events directly against PGlite without a socket. The ported Stage B integration files under test/hosting-*.test.js use test/stageb/boot.js and raw HTTP for Host-header and request-target cases. The existing home, redirects, and boot tests cover Space's public app and forum redirects.

Security and dependencies

Static uploads are validated before storage; tenant content runs on a separate registrable domain and previews use a sandbox CSP. APIs ignore cookies. OpenVibe.Network supplies identity; svc:space needs events.event.publish, billing.usage.record (audience openvibe.billing) once SPACE_BILLING_INTERVAL_MS is on, and, when SPACE_OBJECT_STORE=media, the media.object.upload/read/list/delete grants for the space namespace. OpenVibe.Media may hold tenant objects; OpenVibe.Events receives the outbox when configured. Space's own database is ov_space through openvibe-sdk/db. See SECURITY.md.

Deploy

sudo ovhost deploy space on the host: the release layout under /opt/openvibe.space, /etc/openvibe/space.env, the openvibe-space unit, migrations at boot. The vhosts are deploy/nginx/ (installed with ov-vhost-install).

License

AGPL-3.0-only. See LICENSE.

  • openvibe-contracts: v0.216.0
  • openvibe-sdk: v0.65.0
  • openvibe-shared: v4.15.2