openvibers/openvibe.computer Commits

Serve /release.json, and allow Cloudflare's analytics beacon in the CSP (#8)

OP OpenVibers committed 4 days ago · 47a7158030 · 2 files, +5 −1

The 11-09 browser sweep (tools/site-sweep-browser.js) found two problems on every openvibe.computer page: Shared's navbar release watch polls /release.json, which answered 404, and the CSP refused the Cloudflare Web Analytics beacon (static.cloudflareinsights.com, posting to cloudflareinsights.com), the same fix Studio #2 made. /release.json now comes from openvibe-shared/release; the test checks it.

Changes

ddiff --git a/server/app.js b/server/app.js
iindex 1d38ebb..a84733a 100644
---- a/server/app.js
++++ b/server/app.js
@@@ -15,7 +15,7 @@ function createApp(opts = {}) {
const app = express();
app.disable('x-powered-by'); app.set('trust proxy', config.trustProxy);
app.use(helmet({ contentSecurityPolicy: { directives: {
-- defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network'], styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com'], fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com'], imgSrc: ["'self'", 'data:', 'https://openvibe.network'], connectSrc: ["'self'", 'https://openvibe.network', 'https://openvibe.chat', 'https://billing.openvibe.network', 'https://openvibe.events'], frameSrc: ["'self'", 'https://openvibe.network'], frameAncestors: ["'none'"], objectSrc: ["'none'"], baseUri: ["'self'"], formAction: ["'self'", 'https://openvibe.network'],
++ defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://static.cloudflareinsights.com'], styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com'], fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com'], imgSrc: ["'self'", 'data:', 'https://openvibe.network'], connectSrc: ["'self'", 'https://openvibe.network', 'https://openvibe.chat', 'https://billing.openvibe.network', 'https://openvibe.events', 'https://cloudflareinsights.com'], frameSrc: ["'self'", 'https://openvibe.network'], frameAncestors: ["'none'"], objectSrc: ["'none'"], baseUri: ["'self'"], formAction: ["'self'", 'https://openvibe.network'],
} }, crossOriginEmbedderPolicy: false, referrerPolicy: { policy: 'strict-origin-when-cross-origin' } }));
app.use(express.urlencoded({ extended: false }));
app.use('/auth', sso.router(express));
@@@ -28,6 +28,9 @@ function createApp(opts = {}) {
app.get('/openapi.json', (_req, res) => res.sendFile(path.join(__dirname, '..', 'public', 'openapi.json')));
app.get('/.well-known/agent.json', (_req, res) => res.sendFile(path.join(__dirname, '..', 'public', '.well-known', 'agent.json')));
app.use('/api/v1', createApi({ run, sso }));
++ // GET /release.json (ADR-016): the navbar's release watch polls it so open tabs learn of a new release (the 11-09
++ // browser sweep found it answering 404 here).
++ require('openvibe-shared/release').createRelease({ service: 'computer', root: path.join(__dirname, '..') }).mount(app);
app.use('/shared', require('openvibe-shared/serve').handler());
app.use(express.static(path.join(__dirname, '..', 'public'), { index: false, maxAge: '1h' }));
app.use(createPages({ config, run, sso }));
ddiff --git a/test/computer.test.js b/test/computer.test.js
iindex 58aaef7..30a9086 100644
---- a/test/computer.test.js
++++ b/test/computer.test.js
@@@ -33,6 +33,7 @@ test('home renders signed out and signed in; sign-in and computer controls are v
for (const path of ['/templates', '/pricing', '/docs', '/updates']) { const r = await fetch(`${s.base}${path}`); assert.equal(r.status, 200, `${path} renders signed out`); }
for (const path of ['/templates', '/pricing', '/docs', '/updates']) { const r = await fetch(`${s.base}${path}`, { headers: { cookie: 'ov_token=person-a' } }); assert.equal(r.status, 200, `${path} renders signed in`); }
assert.equal((await fetch(`${s.base}/openapi.json`)).status, 200); assert.equal((await fetch(`${s.base}/.well-known/agent.json`)).status, 200); assert.equal((await fetch(`${s.base}/llms.txt`)).status, 200);
++ { const r = await fetch(`${s.base}/release.json`); assert.equal(r.status, 200, 'the navbar release watch polls /release.json'); assert.equal((await r.json()).service, 'computer'); }
});
test('facade forwards only the presented person token to Run', async (t) => {