openvibers/openvibe.surf Commits

The home's picture is a quiet mark on a phone, buttons wear the room's blue, Ride never promises a map it has not got; docs say what the pages are; contracts v0.232.0, openvibe-shared v4.32.0

OP OpenVibers committed 16 days ago · 47288354ca · 5 files, +31 −31


Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 011ceaf..0dafb9d 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -24,12 +24,12 @@ The service skeleton: three surfs, one room.
same-origin request creates one OpenVibe.Actor task with the person's own Network token from `surf_at` as a
Bearer, an `Idempotency-Key`, and a short browsing brief (search_web, read_page, a desk when a page needs one,
keep sources, finish with a cited report). Answers `{ task_id, page }`; Actor's 4xx refusal keeps its status
-- and words. `/web/go` is the same task as a no-JavaScript form that 303s to the Actor task page.
++ and words. `POST /web/go` is the same task as a no-JavaScript form (this site only) that 303s to the Actor task page.
- **Pages** (`server/http/pages.js`, `server/views/index.js`): `/`, `/ride`, `/ride/:map`, `/watch`, `/web`,
`/developers` and a 404, all server-rendered through the OpenVibe Frame and complete without JavaScript, with
stable `sf-` ids and classes. Public pages are `public, max-age=60` with `Vary: Cookie`; a page rendered for a
-- signed-in person is `private, no-store`. `public/css/surf.css` and `public/js/surf.js` are one-comment
-- placeholders for the main session.
++ signed-in person is `private, no-store`. The room is designed: the run motif and three tiles on the home page, the
++ Watch TV with its guide (clips and moments play in the page over HLS), the maps, and the Web form.
- **Plumbing** (`server/app.js`): helmet with the network's CSP (the Games embed, a possible Live player, the
media edge for HLS), content-hashed `/css` and `/js`, `/api/health`, `/api/ready` (degraded, never 503, when an
optional upstream is down), `/release.json`, `/release-metrics`, `/shared/*`, `/robots.txt`, `/sitemap.xml` and
ddiff --git a/README.md b/README.md
iindex b6f0a32..e956ee0 100644
---- a/README.md
++++ b/README.md
@@@ -96,26 +96,28 @@ form does not start a second task. The answer is `{ "task_id": "tsk_…", "page"
(201, `Location` set). Actor's 4xx refusal (401, 403, 429 allowance/budget, 422) keeps its status and its words;
an Actor that does not answer is a `502 actor.unavailable`.
--`GET /web/go?q=…` is the same task as a plain form for no-JavaScript: it creates the task and **303**s to the
--Actor task page. A guest is sent to sign in; a bad query is a 400; an Actor refusal keeps its status and prints
--its words. It is `private, no-store`.
++`POST /web/go` (form field `q`) is the same task as a plain form for no-JavaScript: it creates the task and
++**303**s to the Actor task page, so the question is never in a URL. It is refused from another site (Origin or
++Sec-Fetch-Site), a guest is sent to sign in, a bad query is a 400 with the form again, and an Actor refusal keeps
++its status and prints its words. It is `private, no-store`; a `GET /web/go` starts nothing and goes back to `/web`.
## Pages
| Route | What it is |
|---|---|
--| `/` | the front door: three tiles, Ride, Web, Watch |
--| `/ride` | the maps list and the embed of the first map |
++| `/` | the Surf room: the run motif (ramps, speed lines, a ticking timer), the three tiles under the hero, scenes, questions |
++| `/ride` | the maps with tier, stages, runs and the record, and the embed of the first map |
| `/ride/:map` | one map: name, tier, stages, records if Games answers, the embed |
--| `/watch` | the feed as a list with each item's thumbnail and a play link; data hooks for the HLS `<video>` |
--| `/web` | the Surf with Vibe form and what it does |
++| `/watch` | the TV: the screen plays clips and moments in the page (HLS), the guide lists every channel; ↑ ↓, a swipe or a tap changes channel; live streams open on their channel |
++| `/web` | the Surf with Vibe form, examples, and what happens next |
| `/developers` | the API, for people and agents |
| anything else | the 404 page |
All of them are server-rendered through the OpenVibe Frame (`openvibe-shared/shell`) and readable without
JavaScript, with stable `sf-` ids and classes. A page rendered for a signed-in person is `private, no-store`; a
--public page is `public, max-age=60` with `Vary: Cookie`. `public/css/surf.css` and `public/js/surf.js` are
--one-comment placeholders: the main session designs them and adds the HLS player.
++public page is `public, max-age=60` with `Vary: Cookie`. `public/js/surf.js` adds what the pages are complete
++without: the TV (native HLS, else `/vendor/hls.light.min.js` 1.7.3, loaded only then), the Web form in the page and
++the home timer; everything works without it.
## API
@@@ -125,7 +127,7 @@ one-comment placeholders: the main session designs them and adds the HLS player.
| `GET /api/v1/ride/maps` | none | `public, max-age=60` | the Games surf map catalogue |
| `GET /api/v1/ride/maps/:id` | none | `public, max-age=60` | one map and its fastest runs |
| `POST /api/v1/web/tasks` | cookie + Origin | `private, no-store` | create one Actor task as the person |
--| `GET /web/go` | cookie | `private, no-store` | the no-JavaScript task form, 303 to Actor |
++| `POST /web/go` | cookie, this site only | `private, no-store` | the no-JavaScript task form, 303 to Actor |
Errors are RFC 9457 `application/problem+json`. A blank map id is 400; a bad Watch topic or cursor is 400. The
only outbound person token is the `Authorization: Bearer` on the request to Actor.
ddiff --git a/STATUS.json b/STATUS.json
iindex ee095ea..b1a2b8d 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -8,36 +8,34 @@
"runtime": "node 22, express 4, openvibe-shared/shell; stateless (no database, no Valkey, no Events)",
"port": "5110",
"domain": "openvibe.surf",
-- "contracts": "openvibe-contracts v0.230.0",
++ "contracts": "openvibe-contracts v0.232.0",
"sdk": "openvibe-sdk v0.70.0",
-- "shared": "openvibe-shared v4.31.0",
++ "shared": "openvibe-shared v4.32.0",
"packages": [
-- "openvibe-contracts v0.230.0",
++ "openvibe-contracts v0.232.0",
"openvibe-sdk v0.70.0",
-- "openvibe-shared v4.31.0"
++ "openvibe-shared v4.32.0"
],
-- "summary": "The service skeleton for openvibe.surf: Network sign-in as OAuth client `surf` (PKCE S256, httpOnly surf_at/surf_rt cookies), the Watch feed merged from OpenVibe.Live (live streams by viewers, then clips and moments interleaved by freshness, no same-channel runs, cached 30 s, each source given 2 s, failures named in `sources`), the Ride proxy to OpenVibe.Games' /api/surf/maps (cached 60 s, games: 'not_ready' while Games' new routes answer 404, an embed URL per map), and Surf with Vibe: a signed-in, same-origin POST that creates one OpenVibe.Actor task with the person's own Network token as a Bearer, an Idempotency-Key and a cited browsing brief, plus /web/go as the no-JavaScript form. The pages are placeholders for the main session: stable sf- ids and classes, semantic HTML, readable without JavaScript.",
++ "summary": "openvibe.surf, the Surf room: Network sign-in as OAuth client `surf`; Ride (OpenVibe.Games' surf maps, cached 60 s, embedded); Watch (a lean-back TV over OpenVibe.Live's live streams, clips and AI moments, clips and moments playing in the page over HLS); Web (Surf with Vibe: one OpenVibe.Actor task made with the person's own Network token). Stateless.",
"works": [
"Sign-in with OpenVibe.Network: OAuth 2 authorization code, PKCE S256, state check, server-side exchange, httpOnly surf_at/surf_rt cookies, sanitizeNext (own origins only, no control characters or backslashes)",
"Watch GET /api/v1/watch/feed?topic=all|live|clips|moments&cursor=: merges OpenVibe.Live's /api/streams, /api/content/feed?type=clips and /api/content/moments?type=clips into one item shape, ranks live by viewers then moments/clips by freshness with no channel twice in a row, caches 30 s, 2 s per source, a failing source left out and named in sources, public max-age=30",
"Ride GET /api/v1/ride/maps and /api/v1/ride/maps/:id: proxies OpenVibe.Games' /api/surf/maps routes, adds each map's embed_url (https://openvibe.games/play/surf?map=<id>&embed=1), caches 60 s, Games 404 → empty list/map shell with games: 'not_ready'",
"Web POST /api/v1/web/tasks: signed in, same-origin, query 3–500 characters, sends the person's surf_at token to OpenVibe.Actor as a Bearer with an Idempotency-Key and the prefixed browsing brief, answers { task_id, page }, and passes Actor's 4xx refusal through in words",
-- "GET /web/go?q=: the same task as a plain form for no-JavaScript: 303 to the Actor task page, sign-in redirect for a guest, Actor's refusal in plain words",
-- "Server-rendered pages: / (three tiles), /ride (maps list and first embed), /ride/:map (name, tier, stages, records, embed), /watch (feed list with thumbnails and play links, HLS hooks for the main session's video), /web (the form), /developers and a 404; public max-age=60 with Vary: Cookie, signed-in private, no-store",
++ "POST /web/go: the same task as a plain form for no-JavaScript (this site only, the question never in a URL): 303 to the Actor task page, sign-in redirect for a guest, Actor's refusal in plain words",
++ "Designed pages: / (the run motif, three tiles, scenes, questions), /ride and /ride/:map, /watch (the TV and its guide, HLS in the page), /web, /developers and a 404; public max-age=60 with Vary: Cookie, signed-in private, no-store",
"Crawl artifacts (robots.txt, sitemap.xml with the public pages and Ride maps, llms.txt), /api/health, /api/ready (degraded when Network/Live/Games/Actor do not answer), /release.json, /release-metrics, /shared/*",
"Helmet with the network's CSP (Games and Live frames, openvibe.media HLS), per-IP 120/min on /api and /auth, content-hashed /css and /js, graceful stop",
"Deploy files: openvibe-surf.service, nginx vhost for openvibe.surf on 127.0.0.1:5110 with the forms zone, /auth/me on the API zone and /internal + /metrics 404",
"Tests: feed merge/order/shape/failing source/30 s cache/cursor, ride proxy/cache/not_ready/failure, web 401/403/Actor Bearer + Idempotency-Key + prefixed text/refusal/redirect, SSO (Design's cases), pages/cache headers/CSP, discovery"
],
"notYet": [
-- "The pages' design and public/css/surf.css + public/js/surf.js: the main session writes them; today the views are semantic placeholders and the assets are one-comment files (the HLS <video> player is the main session's script)",
-- "OpenVibe.Games' GET /api/surf/maps and /api/surf/maps/:id are being added in parallel; until they ship, Ride answers games: 'not_ready'",
-- "A Surf service manifest and capabilities in OpenVibe.Contracts: this service has no capability of its own and no other service calls it",
-- "Deployment: the deploy files are written, but the service is not deployed yet"
++ "OpenVibe.Games' surf mode and GET /api/surf/maps: until they ship, Ride answers games: 'not_ready' and the page says the maps are being built",
++ "Live streams in the Watch TV itself: they open on their channel until a Live embed player exists"
],
"capabilitiesRegistered": false,
-- "serviceManifestRegistered": false,
-- "deployed": false,
++ "serviceManifestRegistered": true,
++ "deployed": true,
"placeholderInSites": false,
"features": [
"Network sign-in (PKCE)",
ddiff --git a/package-lock.json b/package-lock.json
iindex 7514528..fffcb54 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -14,7 +14,7 @@
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.230.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.232.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.70.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.32.0"
},
@@@ -784,9 +784,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.230.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.230.0",
-- "integrity": "sha512-wvzSYV0GKfHV6UnEKtqDAXkrl3yimdWe/KHM0jeU0JWkrRo93zGNAZ2fRPwATBeihITVE0b973dM899U/YOzgw==",
++ "version": "0.232.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.232.0",
++ "integrity": "sha512-6HI5nn//nAUEDdG4xRTAlcb40oc/6yO1nx7R5exGZ6Bo3mL5fJ5szw9IONddoLN6qJsO1CXzB5TzTqkBAh3OzQ==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex 0bbcf7f..f2f858c 100644
---- a/package.json
++++ b/package.json
@@@ -20,7 +20,7 @@
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.230.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.232.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.70.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.32.0"
},