openvibers/openvibe.search Commits
The OpenVibe Frame from this site's own pinned copy: /shared/* is served by openvibe-shared/serve (1.12.0) and every page references it by content hash (/shared/<file>?v=<hash>), so this site's pin decides what its pages run and its navbar and footer keep working while openvibe.network is down
Changes
@@@ -81,6 +81,8 @@ server {location = /robots.txt { proxy_pass http://127.0.0.1:4710; }# The OpenVibe Frame's same-origin init script, and what shipped on this site (the shared log).location = /frame-init.js { limit_except GET { deny all; } proxy_pass http://127.0.0.1:4710; }++ # This site's own pinned copy of the Frame's browser files (openvibe-shared/serve).++ location ^~ /shared/ { limit_except GET { deny all; } proxy_pass http://127.0.0.1:4710; }location = /updates {limit_except GET { deny all; }limit_req zone=ovsearch_query burst=40 nodelay;@@@ -15,7 +15,7 @@"dotenv": "^16.4.7","express": "^4.21.2","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.1"++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.12.0"},"engines": {"node": ">=22.0.0"@@@ -985,9 +985,9 @@}},"node_modules/openvibe-shared": {-- "version": "1.11.1",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.1",-- "integrity": "sha512-hBaZlZRVZjkGfsPQE16rQIou2lUuusADea3Evx1tVjB84FTHGHS7ZALfcXaNOk7dR53HOVTJrQ0njmScdreUiw==",++ "version": "1.12.0",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.12.0",++ "integrity": "sha512-Qpy4YVoPMs1q/0/08/5ZODI0+7ev+Krk75nsRPsTjNCm7Eu91tt1LPnUNLt4kYfRj6duS+N9icm02gksnlMiyA==","license": "MIT","dependencies": {"jsonwebtoken": "^9.0.0"@@@ -21,7 +21,7 @@"dotenv": "^16.4.7","express": "^4.21.2","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.1"++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.12.0"},"engines": {"node": ">=22.0.0"@@@ -32,6 +32,8 @@ function createApp({ config, db, store, engine, auth, keys, outbox, relay, purge});// The webhook reads its raw body itself (the signature covers the exact bytes).++ // This site's own pinned copy of the OpenVibe Frame's browser files (openvibe-shared/serve).++ app.use('/shared', require('openvibe-shared/serve').handler());app.use(webhookRouter({ config, db, store, relay, log, now }));app.use('/api', express.json({ limit: config.maxBodyBytes, type: ['application/json', 'application/*+json'] }));@@@ -11,6 +11,7 @@* pages are noindex. Clients that do not ask for HTML get the plain-text route index at /.*/const express = require('express');++const ovServe = require('openvibe-shared/serve');const { AuthError, ANONYMOUS } = require('../auth');const { QueryError, one } = require('../api/query');@@@ -80,9 +81,9 @@ function layout({ title, q, owner, type, body, noindex }) {${noindex ? '<meta name="robots" content="noindex, nofollow">\n' : ''}<meta name="description" content="Search what the OpenVibe network's services have published."><meta name="color-scheme" content="light dark">${require('openvibe-shared/app-icon').headTags({ site: 'network', iconBase: `${NETWORK}/assets` }).split('\n').filter((l) => l.startsWith('<link')).join('\n')}--<script src="${NETWORK}/shared/theme-loader.js" defer></script>--<script src="${NETWORK}/shared/navbar.js" defer></script>--<script src="${NETWORK}/shared/footer.js" defer></script>++<script src="${ovServe.url('theme-loader.js')}" defer></script>++<script src="${ovServe.url('navbar.js')}" defer></script>++<script src="${ovServe.url('footer.js')}" defer></script><script src="/frame-init.js" defer></script><style>:root { --bg: #fff; --fg: #1a1a1a; --muted: #5c5c66; --line: #dcdce3; --accent: #2456d6; --mark: #fff2a8; }@@@ -155,7 +156,7 @@ function pageRouter({ searcher, auth }) {res.setHeader('Content-Security-Policy', CSP);res.setHeader('X-Frame-Options', 'DENY');res.setHeader('Cache-Control', 'public, max-age=60');-- res.type('html').send(layout({ title: 'What shipped on OpenVibe.Search', q: '', owner: '', type: '', body: frame.updatesBody({ service: 'search', siteName: 'OpenVibe.Search' }) + frame.shippedScript() }));++ res.type('html').send(layout({ title: 'What shipped on OpenVibe.Search', q: '', owner: '', type: '', body: frame.updatesBody({ service: 'search', siteName: 'OpenVibe.Search' }) + `<script src="${ovServe.url('shipped.js')}" defer></script>` }));});router.get('/robots.txt', (_req, res) => {@@@ -29,6 +29,7 @@ t('/metrics is 404; owner API, webhook and document writes are loopback-only', (assert.match(conf, /location = \/metrics \{ return 404; \}/);assert.match(conf, /location = \/frame-init\.js \{ limit_except GET \{ deny all; \} proxy_pass http:\/\/127\.0\.0\.1:4710; \}/, 'the Frame init script');assert.match(block('location = /updates'), /limit_except GET \{ deny all; \}/, 'the update log, GET only');++ assert.match(conf, /location \^~ \/shared\/ \{ limit_except GET \{ deny all; \} proxy_pass http:\/\/127\.0\.0\.1:4710; \}/, 'the site\'s own Frame files');assert.match(block('location ^~ /internal/'), loopbackOnly);assert.match(block('location ^~ /api/v1/owners/'), loopbackOnly);assert.match(block('location ^~ /api/v1/documents/'), /limit_except GET \{\s*allow 127\.0\.0\.1;\s*allow ::1;\s*deny all;/);
@@ -81,6 +81,8 @@ server {
@@ -81,6 +81,8 @@ server {
location = /robots.txt { proxy_pass http://127.0.0.1:4710; }
location = /robots.txt { proxy_pass http://127.0.0.1:4710; }
# The OpenVibe Frame's same-origin init script, and what shipped on this site (the shared log).
# The OpenVibe Frame's same-origin init script, and what shipped on this site (the shared log).
location = /frame-init.js { limit_except GET { deny all; } proxy_pass http://127.0.0.1:4710; }
location = /frame-init.js { limit_except GET { deny all; } proxy_pass http://127.0.0.1:4710; }
+ # This site's own pinned copy of the Frame's browser files (openvibe-shared/serve).
+ location ^~ /shared/ { limit_except GET { deny all; } proxy_pass http://127.0.0.1:4710; }
location = /updates {
location = /updates {
limit_except GET { deny all; }
limit_except GET { deny all; }
limit_req zone=ovsearch_query burst=40 nodelay;
limit_req zone=ovsearch_query burst=40 nodelay;
@@ -15,7 +15,7 @@
@@ -15,7 +15,7 @@
"dotenv": "^16.4.7",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"express": "^4.21.2",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.1"
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.12.0"
},
},
"engines": {
"engines": {
"node": ">=22.0.0"
"node": ">=22.0.0"
@@ -985,9 +985,9 @@
@@ -985,9 +985,9 @@
}
}
},
},
"node_modules/openvibe-shared": {
"node_modules/openvibe-shared": {
- "version": "1.11.1",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.1",
- "integrity": "sha512-hBaZlZRVZjkGfsPQE16rQIou2lUuusADea3Evx1tVjB84FTHGHS7ZALfcXaNOk7dR53HOVTJrQ0njmScdreUiw==",
+ "version": "1.12.0",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.12.0",
+ "integrity": "sha512-Qpy4YVoPMs1q/0/08/5ZODI0+7ev+Krk75nsRPsTjNCm7Eu91tt1LPnUNLt4kYfRj6duS+N9icm02gksnlMiyA==",
"license": "MIT",
"license": "MIT",
"dependencies": {
"dependencies": {
"jsonwebtoken": "^9.0.0"
"jsonwebtoken": "^9.0.0"
@@ -21,7 +21,7 @@
@@ -21,7 +21,7 @@
"dotenv": "^16.4.7",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"express": "^4.21.2",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.33.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.11.1"
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v1.12.0"
},
},
"engines": {
"engines": {
"node": ">=22.0.0"
"node": ">=22.0.0"
@@ -32,6 +32,8 @@ function createApp({ config, db, store, engine, auth, keys, outbox, relay, purge
@@ -32,6 +32,8 @@ function createApp({ config, db, store, engine, auth, keys, outbox, relay, purge
});
});
// The webhook reads its raw body itself (the signature covers the exact bytes).
// The webhook reads its raw body itself (the signature covers the exact bytes).
+ // This site's own pinned copy of the OpenVibe Frame's browser files (openvibe-shared/serve).
+ app.use('/shared', require('openvibe-shared/serve').handler());
app.use(webhookRouter({ config, db, store, relay, log, now }));
app.use(webhookRouter({ config, db, store, relay, log, now }));
app.use('/api', express.json({ limit: config.maxBodyBytes, type: ['application/json', 'application/*+json'] }));
app.use('/api', express.json({ limit: config.maxBodyBytes, type: ['application/json', 'application/*+json'] }));
@@ -11,6 +11,7 @@
@@ -11,6 +11,7 @@
* pages are noindex. Clients that do not ask for HTML get the plain-text route index at /.
* pages are noindex. Clients that do not ask for HTML get the plain-text route index at /.
*/
*/
const express = require('express');
const express = require('express');
+const ovServe = require('openvibe-shared/serve');
const { AuthError, ANONYMOUS } = require('../auth');
const { AuthError, ANONYMOUS } = require('../auth');
const { QueryError, one } = require('../api/query');
const { QueryError, one } = require('../api/query');
@@ -80,9 +81,9 @@ function layout({ title, q, owner, type, body, noindex }) {
@@ -80,9 +81,9 @@ function layout({ title, q, owner, type, body, noindex }) {
${noindex ? '<meta name="robots" content="noindex, nofollow">\n' : ''}<meta name="description" content="Search what the OpenVibe network's services have published.">
${noindex ? '<meta name="robots" content="noindex, nofollow">\n' : ''}<meta name="description" content="Search what the OpenVibe network's services have published.">
<meta name="color-scheme" content="light dark">
<meta name="color-scheme" content="light dark">
${require('openvibe-shared/app-icon').headTags({ site: 'network', iconBase: `${NETWORK}/assets` }).split('\n').filter((l) => l.startsWith('<link')).join('\n')}
${require('openvibe-shared/app-icon').headTags({ site: 'network', iconBase: `${NETWORK}/assets` }).split('\n').filter((l) => l.startsWith('<link')).join('\n')}
-<script src="${NETWORK}/shared/theme-loader.js" defer></script>
-<script src="${NETWORK}/shared/navbar.js" defer></script>
-<script src="${NETWORK}/shared/footer.js" defer></script>
+<script src="${ovServe.url('theme-loader.js')}" defer></script>
+<script src="${ovServe.url('navbar.js')}" defer></script>
+<script src="${ovServe.url('footer.js')}" defer></script>
<script src="/frame-init.js" defer></script>
<script src="/frame-init.js" defer></script>
<style>
<style>
:root { --bg: #fff; --fg: #1a1a1a; --muted: #5c5c66; --line: #dcdce3; --accent: #2456d6; --mark: #fff2a8; }
:root { --bg: #fff; --fg: #1a1a1a; --muted: #5c5c66; --line: #dcdce3; --accent: #2456d6; --mark: #fff2a8; }
@@ -155,7 +156,7 @@ function pageRouter({ searcher, auth }) {
@@ -155,7 +156,7 @@ function pageRouter({ searcher, auth }) {
res.setHeader('Content-Security-Policy', CSP);
res.setHeader('Content-Security-Policy', CSP);
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('Cache-Control', 'public, max-age=60');
res.setHeader('Cache-Control', 'public, max-age=60');
- res.type('html').send(layout({ title: 'What shipped on OpenVibe.Search', q: '', owner: '', type: '', body: frame.updatesBody({ service: 'search', siteName: 'OpenVibe.Search' }) + frame.shippedScript() }));
+ res.type('html').send(layout({ title: 'What shipped on OpenVibe.Search', q: '', owner: '', type: '', body: frame.updatesBody({ service: 'search', siteName: 'OpenVibe.Search' }) + `<script src="${ovServe.url('shipped.js')}" defer></script>` }));
});
});
router.get('/robots.txt', (_req, res) => {
router.get('/robots.txt', (_req, res) => {
@@ -29,6 +29,7 @@ t('/metrics is 404; owner API, webhook and document writes are loopback-only', (
@@ -29,6 +29,7 @@ t('/metrics is 404; owner API, webhook and document writes are loopback-only', (
assert.match(conf, /location = \/metrics \{ return 404; \}/);
assert.match(conf, /location = \/metrics \{ return 404; \}/);
assert.match(conf, /location = \/frame-init\.js \{ limit_except GET \{ deny all; \} proxy_pass http:\/\/127\.0\.0\.1:4710; \}/, 'the Frame init script');
assert.match(conf, /location = \/frame-init\.js \{ limit_except GET \{ deny all; \} proxy_pass http:\/\/127\.0\.0\.1:4710; \}/, 'the Frame init script');
assert.match(block('location = /updates'), /limit_except GET \{ deny all; \}/, 'the update log, GET only');
assert.match(block('location = /updates'), /limit_except GET \{ deny all; \}/, 'the update log, GET only');
+ assert.match(conf, /location \^~ \/shared\/ \{ limit_except GET \{ deny all; \} proxy_pass http:\/\/127\.0\.0\.1:4710; \}/, 'the site\'s own Frame files');
assert.match(block('location ^~ /internal/'), loopbackOnly);
assert.match(block('location ^~ /internal/'), loopbackOnly);
assert.match(block('location ^~ /api/v1/owners/'), loopbackOnly);
assert.match(block('location ^~ /api/v1/owners/'), loopbackOnly);
assert.match(block('location ^~ /api/v1/documents/'), /limit_except GET \{\s*allow 127\.0\.0\.1;\s*allow ::1;\s*deny all;/);
assert.match(block('location ^~ /api/v1/documents/'), /limit_except GET \{\s*allow 127\.0\.0\.1;\s*allow ::1;\s*deny all;/);