openvibers/openvibe.ai Commits
AI: the retired ai.openvibe.network vhost is deleted (plan T6) (#40)
Changes
@@@ -1,6 +1,6 @@# ═══════════════════════════════════════════════════════════════# ai.openvibe.services — OpenVibe.AI Environment Configuration--# The public home and API origin (ai.openvibe.network answers 301 to it). BASE_URL defaults to it in production.++# The public home and API origin. BASE_URL defaults to it in production.# Copy to .env and fill in values. In production this lives at /etc/openvibe/ai.env (0600).# Secrets are read by NAME only (providers store 'env:NAME' references); nothing logs or returns them.# ═══════════════════════════════════════════════════════════════@@@ -6,7 +6,7 @@production use: OpenVibe.Live runs with `AI_SERVICE=remote` and Network's footer copy runs`network.site_copy` here. Public since 2026-10-07 at [ai.openvibe.services](https://ai.openvibe.services):the home (`server/home.js`), `/stats` and the developer-app API (`ai.app.run`).--**Domain:** `ai.openvibe.services` (`ai.openvibe.network` answers 301 to it) · **Port:** 4700 · **Unit:** `openvibe-ai.service`++**Domain:** `ai.openvibe.services` · **Port:** 4700 · **Unit:** `openvibe-ai.service`**Plan:** OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §12.1, §12.13, §15.14, §33, §34.**License:** AGPL-3.0 (same as every OpenVibe service).@@@ -445,7 +445,7 @@ principal `ai`. The vhost `deploy/nginx/ai.openvibe.services.conf` (on the `*.opserves the home, `/stats`, `/shared/*`, `/robots.txt`, `/sitemap.xml`, `/llms.txt`, health/ready, the operatorconsole `/console` with its sign-in `/auth/`, and exactly the developer-app routes (the six operations by POST,`/api/v1/runs/:id` by GET, rate-limited per address); every other `/api/` path and `/metrics` stay host-local.--`deploy/nginx/ai.openvibe.network.conf` answers 301 to the same path on ai.openvibe.services. The console needs++The old `ai.openvibe.network` address was retired on 2026-10-10. The console needs`AI_CONSOLE_SESSION_SECRET` (32+ random characters) and `OV_OAUTH_CLIENT_SECRET` in the env file (without them itanswers 503 in production); Network client `ai` lists `https://ai.openvibe.services/auth/callback`.@@@ -6,7 +6,7 @@"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)","runtime": "node 22, express, postgresql","port": 4700,-- "domain": "ai.openvibe.network still serves the OpenVibe.Sites placeholder; the service runs on openvibe-ovh (/opt/openvibe.ai, unit openvibe-ai) on 127.0.0.1:4700, loopback only, used by OpenVibe.Live and OpenVibe.Network",++ "domain": "ai.openvibe.services (the old ai.openvibe.network address was retired on 2026-10-10); the service runs on openvibe-ovh (/opt/openvibe.ai, unit openvibe-ai) on 127.0.0.1:4700 behind nginx; OpenVibe.Live and OpenVibe.Network call it on loopback","contracts": "openvibe-contracts v0.126.0","sdk": "openvibe-sdk v0.35.0","shared": "openvibe-shared v2.20.3",ddeleted file mode 100644@@@ -1,35 +0,0 @@--## ═══════════════════════════════════════════════════════════════--## ai.openvibe.network — Nginx Configuration (REFERENCE)--##--## Deployed to /etc/nginx/sites-available/ai.openvibe.network.conf — keep them in sync, and reload--## nginx after changing it. OpenVibe.AI's public origin is https://ai.openvibe.services--## (deploy/nginx/ai.openvibe.services.conf); this name answers 301 to the same path there.--## Services on this host never come through here: they call 127.0.0.1:4700 directly.--## ═══════════════════════════════════════════════════════════════----server {-- listen 80;-- listen [::]:80;-- server_name ai.openvibe.network;---- location /.well-known/acme-challenge/ { root /var/www/certbot; }-- location / { return 301 https://ai.openvibe.services$request_uri; }--}----server {-- listen 443 ssl;-- listen [::]:443 ssl;-- http2 on;-- server_name ai.openvibe.network;---- ssl_certificate /etc/letsencrypt/live/openvibe.network/fullchain.pem;-- ssl_certificate_key /etc/letsencrypt/live/openvibe.network/privkey.pem;-- ssl_protocols TLSv1.2 TLSv1.3;---- access_log /var/log/nginx/ai.openvibe.network.access.log;-- error_log /var/log/nginx/ai.openvibe.network.error.log;---- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;---- location / { return 301 https://ai.openvibe.services$request_uri; }--}@@@ -4,8 +4,8 @@## Deployed to /etc/nginx/sites-available/ai.openvibe.services.conf — keep them in sync, and reload## nginx after changing it. It uses the *.openvibe.services certificate the host already holds## (/etc/letsencrypt/live/openvibe.services/); installed in place of the OpenVibe.Sites placeholder--## vhost of the same name, it replaces that placeholder. ai.openvibe.network (its own vhost) answers--## 301 to here.++## vhost of the same name, it replaces that placeholder. The old ai.openvibe.network address was retired on++## 2026-10-10 (its last service caller stopped on 10-02).#### The Node service (port 4700, systemd unit openvibe-ai) serves:## / the product home for a browser (server/home.js), the text API index for anything else@@@ -8,8 +8,7 @@"status": "alpha","repository": "OpenVibers/OpenVibe.AI","domains": [-- "ai.openvibe.services",-- "ai.openvibe.network"++ "ai.openvibe.services"],"publicOrigin": "https://ai.openvibe.services","health": "/api/health",@@@ -77,14 +76,14 @@],"window": "automatic only while ovhost waits for readiness after the restart (30 s in host.example.json); manual afterwards, as long as no blocker applies","blockers": {-- "none": "the schema code only adds (CREATE \u2026 IF NOT EXISTS, ADD COLUMN; no DROP, RENAME or table rebuild), which an older release ignores"++ "none": "the schema code only adds (CREATE … IF NOT EXISTS, ADD COLUMN; no DROP, RENAME or table rebuild), which an older release ignores"}},"contracts": {"range": ">=0.6.0 <1.0.0"},"leases": {-- "none": "no claims: one process owns ai.db (better-sqlite3, single writer); a run is taken with a compare-and-set on its status (queued \u2192 running)"++ "none": "no claims: one process owns ai.db (better-sqlite3, single writer); a run is taken with a compare-and-set on its status (queued → running)"}},"notes": "Providers, models, routing profiles, versioned prompt templates and workflows, runs, request logs, citations, scoped cache, quotas and audit. Workflow output is a draft/evidence package attributed to workflow + model + run. ai.run.queued|succeeded|failed|cached have payload contracts (v0.30.0, status planned): AI publishes them once its Events client is wired in; it publishes none today. ai.run.create takes ai.run-request@1 and returns ai.run@1."@@@ -2,7 +2,7 @@// The public home (plan T6: AI as a developer product). ai.openvibe.services renders server/home.js for a// browser and keeps the text/plain API index for curl and API clients, serves the pinned OpenVibe Frame at// /shared, and answers robots.txt, sitemap.xml and llms.txt. The vhosts: the developer-app routes are the only--// API the public vhost proxies, and ai.openvibe.network is a 301 to the product origin.++// API the public vhost proxies, and the old ai.openvibe.network address is retired (no vhost of its own).const assert = require('assert');const fs = require('fs');const path = require('path');@@@ -87,10 +87,8 @@ t.test('the public vhost proxies the home, its files and exactly the developer-aassert.ok(!conf.includes('$proxy_add_x_forwarded_for'));});--t.test('ai.openvibe.network answers 301 to the same path on ai.openvibe.services, and proxies nothing', () => {-- const conf = active('ai.openvibe.network.conf');-- assert.ok(!conf.includes('proxy_pass'), 'nothing is served under the old name');-- assert.strictEqual((conf.match(/return 301 https:\/\/ai\.openvibe\.services\$request_uri;/g) || []).length, 2, 'HTTP and HTTPS');++t.test('the retired ai.openvibe.network address has no vhost (plan T6, 2026-10-10)', () => {++ assert.ok(!fs.existsSync(path.join(__dirname, '..', 'deploy', 'nginx', 'ai.openvibe.network.conf')));});t.test('the CSPs let Cloudflare Web Analytics load and report (it injects its beacon on this zone)', async () => {
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
# ═══════════════════════════════════════════════════════════════
# ═══════════════════════════════════════════════════════════════
# ai.openvibe.services — OpenVibe.AI Environment Configuration
# ai.openvibe.services — OpenVibe.AI Environment Configuration
-# The public home and API origin (ai.openvibe.network answers 301 to it). BASE_URL defaults to it in production.
+# The public home and API origin. BASE_URL defaults to it in production.
# Copy to .env and fill in values. In production this lives at /etc/openvibe/ai.env (0600).
# Copy to .env and fill in values. In production this lives at /etc/openvibe/ai.env (0600).
# Secrets are read by NAME only (providers store 'env:NAME' references); nothing logs or returns them.
# Secrets are read by NAME only (providers store 'env:NAME' references); nothing logs or returns them.
# ═══════════════════════════════════════════════════════════════
# ═══════════════════════════════════════════════════════════════
@@ -6,7 +6,7 @@
@@ -6,7 +6,7 @@
production use: OpenVibe.Live runs with `AI_SERVICE=remote` and Network's footer copy runs
production use: OpenVibe.Live runs with `AI_SERVICE=remote` and Network's footer copy runs
`network.site_copy` here. Public since 2026-10-07 at [ai.openvibe.services](https://ai.openvibe.services):
`network.site_copy` here. Public since 2026-10-07 at [ai.openvibe.services](https://ai.openvibe.services):
the home (`server/home.js`), `/stats` and the developer-app API (`ai.app.run`).
the home (`server/home.js`), `/stats` and the developer-app API (`ai.app.run`).
-**Domain:** `ai.openvibe.services` (`ai.openvibe.network` answers 301 to it) · **Port:** 4700 · **Unit:** `openvibe-ai.service`
+**Domain:** `ai.openvibe.services` · **Port:** 4700 · **Unit:** `openvibe-ai.service`
**Plan:** OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §12.1, §12.13, §15.14, §33, §34.
**Plan:** OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §12.1, §12.13, §15.14, §33, §34.
**License:** AGPL-3.0 (same as every OpenVibe service).
**License:** AGPL-3.0 (same as every OpenVibe service).
@@ -445,7 +445,7 @@ principal `ai`. The vhost `deploy/nginx/ai.openvibe.services.conf` (on the `*.op
@@ -445,7 +445,7 @@ principal `ai`. The vhost `deploy/nginx/ai.openvibe.services.conf` (on the `*.op
serves the home, `/stats`, `/shared/*`, `/robots.txt`, `/sitemap.xml`, `/llms.txt`, health/ready, the operator
serves the home, `/stats`, `/shared/*`, `/robots.txt`, `/sitemap.xml`, `/llms.txt`, health/ready, the operator
console `/console` with its sign-in `/auth/`, and exactly the developer-app routes (the six operations by POST,
console `/console` with its sign-in `/auth/`, and exactly the developer-app routes (the six operations by POST,
`/api/v1/runs/:id` by GET, rate-limited per address); every other `/api/` path and `/metrics` stay host-local.
`/api/v1/runs/:id` by GET, rate-limited per address); every other `/api/` path and `/metrics` stay host-local.
-`deploy/nginx/ai.openvibe.network.conf` answers 301 to the same path on ai.openvibe.services. The console needs
+The old `ai.openvibe.network` address was retired on 2026-10-10. The console needs
`AI_CONSOLE_SESSION_SECRET` (32+ random characters) and `OV_OAUTH_CLIENT_SECRET` in the env file (without them it
`AI_CONSOLE_SESSION_SECRET` (32+ random characters) and `OV_OAUTH_CLIENT_SECRET` in the env file (without them it
answers 503 in production); Network client `ai` lists `https://ai.openvibe.services/auth/callback`.
answers 503 in production); Network client `ai` lists `https://ai.openvibe.services/auth/callback`.
@@ -6,7 +6,7 @@
@@ -6,7 +6,7 @@
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"runtime": "node 22, express, postgresql",
"runtime": "node 22, express, postgresql",
"port": 4700,
"port": 4700,
- "domain": "ai.openvibe.network still serves the OpenVibe.Sites placeholder; the service runs on openvibe-ovh (/opt/openvibe.ai, unit openvibe-ai) on 127.0.0.1:4700, loopback only, used by OpenVibe.Live and OpenVibe.Network",
+ "domain": "ai.openvibe.services (the old ai.openvibe.network address was retired on 2026-10-10); the service runs on openvibe-ovh (/opt/openvibe.ai, unit openvibe-ai) on 127.0.0.1:4700 behind nginx; OpenVibe.Live and OpenVibe.Network call it on loopback",
"contracts": "openvibe-contracts v0.126.0",
"contracts": "openvibe-contracts v0.126.0",
"sdk": "openvibe-sdk v0.35.0",
"sdk": "openvibe-sdk v0.35.0",
"shared": "openvibe-shared v2.20.3",
"shared": "openvibe-shared v2.20.3",
deleted file mode 100644
deleted file mode 100644
@@ -1,35 +0,0 @@
@@ -1,35 +0,0 @@
-## ═══════════════════════════════════════════════════════════════
-## ai.openvibe.network — Nginx Configuration (REFERENCE)
-##
-## Deployed to /etc/nginx/sites-available/ai.openvibe.network.conf — keep them in sync, and reload
-## nginx after changing it. OpenVibe.AI's public origin is https://ai.openvibe.services
-## (deploy/nginx/ai.openvibe.services.conf); this name answers 301 to the same path there.
-## Services on this host never come through here: they call 127.0.0.1:4700 directly.
-## ═══════════════════════════════════════════════════════════════
-
-server {
- listen 80;
- listen [::]:80;
- server_name ai.openvibe.network;
-
- location /.well-known/acme-challenge/ { root /var/www/certbot; }
- location / { return 301 https://ai.openvibe.services$request_uri; }
-}
-
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- http2 on;
- server_name ai.openvibe.network;
-
- ssl_certificate /etc/letsencrypt/live/openvibe.network/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/openvibe.network/privkey.pem;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- access_log /var/log/nginx/ai.openvibe.network.access.log;
- error_log /var/log/nginx/ai.openvibe.network.error.log;
-
- add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
-
- location / { return 301 https://ai.openvibe.services$request_uri; }
-}
@@ -4,8 +4,8 @@
@@ -4,8 +4,8 @@
## Deployed to /etc/nginx/sites-available/ai.openvibe.services.conf — keep them in sync, and reload
## Deployed to /etc/nginx/sites-available/ai.openvibe.services.conf — keep them in sync, and reload
## nginx after changing it. It uses the *.openvibe.services certificate the host already holds
## nginx after changing it. It uses the *.openvibe.services certificate the host already holds
## (/etc/letsencrypt/live/openvibe.services/); installed in place of the OpenVibe.Sites placeholder
## (/etc/letsencrypt/live/openvibe.services/); installed in place of the OpenVibe.Sites placeholder
-## vhost of the same name, it replaces that placeholder. ai.openvibe.network (its own vhost) answers
-## 301 to here.
+## vhost of the same name, it replaces that placeholder. The old ai.openvibe.network address was retired on
+## 2026-10-10 (its last service caller stopped on 10-02).
##
##
## The Node service (port 4700, systemd unit openvibe-ai) serves:
## The Node service (port 4700, systemd unit openvibe-ai) serves:
## / the product home for a browser (server/home.js), the text API index for anything else
## / the product home for a browser (server/home.js), the text API index for anything else
@@ -8,8 +8,7 @@
@@ -8,8 +8,7 @@
"status": "alpha",
"status": "alpha",
"repository": "OpenVibers/OpenVibe.AI",
"repository": "OpenVibers/OpenVibe.AI",
"domains": [
"domains": [
- "ai.openvibe.services",
- "ai.openvibe.network"
+ "ai.openvibe.services"
],
],
"publicOrigin": "https://ai.openvibe.services",
"publicOrigin": "https://ai.openvibe.services",
"health": "/api/health",
"health": "/api/health",
@@ -77,14 +76,14 @@
@@ -77,14 +76,14 @@
],
],
"window": "automatic only while ovhost waits for readiness after the restart (30 s in host.example.json); manual afterwards, as long as no blocker applies",
"window": "automatic only while ovhost waits for readiness after the restart (30 s in host.example.json); manual afterwards, as long as no blocker applies",
"blockers": {
"blockers": {
- "none": "the schema code only adds (CREATE \u2026 IF NOT EXISTS, ADD COLUMN; no DROP, RENAME or table rebuild), which an older release ignores"
+ "none": "the schema code only adds (CREATE … IF NOT EXISTS, ADD COLUMN; no DROP, RENAME or table rebuild), which an older release ignores"
}
}
},
},
"contracts": {
"contracts": {
"range": ">=0.6.0 <1.0.0"
"range": ">=0.6.0 <1.0.0"
},
},
"leases": {
"leases": {
- "none": "no claims: one process owns ai.db (better-sqlite3, single writer); a run is taken with a compare-and-set on its status (queued \u2192 running)"
+ "none": "no claims: one process owns ai.db (better-sqlite3, single writer); a run is taken with a compare-and-set on its status (queued → running)"
}
}
},
},
"notes": "Providers, models, routing profiles, versioned prompt templates and workflows, runs, request logs, citations, scoped cache, quotas and audit. Workflow output is a draft/evidence package attributed to workflow + model + run. ai.run.queued|succeeded|failed|cached have payload contracts (v0.30.0, status planned): AI publishes them once its Events client is wired in; it publishes none today. ai.run.create takes ai.run-request@1 and returns ai.run@1."
"notes": "Providers, models, routing profiles, versioned prompt templates and workflows, runs, request logs, citations, scoped cache, quotas and audit. Workflow output is a draft/evidence package attributed to workflow + model + run. ai.run.queued|succeeded|failed|cached have payload contracts (v0.30.0, status planned): AI publishes them once its Events client is wired in; it publishes none today. ai.run.create takes ai.run-request@1 and returns ai.run@1."
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
// The public home (plan T6: AI as a developer product). ai.openvibe.services renders server/home.js for a
// The public home (plan T6: AI as a developer product). ai.openvibe.services renders server/home.js for a
// browser and keeps the text/plain API index for curl and API clients, serves the pinned OpenVibe Frame at
// browser and keeps the text/plain API index for curl and API clients, serves the pinned OpenVibe Frame at
// /shared, and answers robots.txt, sitemap.xml and llms.txt. The vhosts: the developer-app routes are the only
// /shared, and answers robots.txt, sitemap.xml and llms.txt. The vhosts: the developer-app routes are the only
-// API the public vhost proxies, and ai.openvibe.network is a 301 to the product origin.
+// API the public vhost proxies, and the old ai.openvibe.network address is retired (no vhost of its own).
const assert = require('assert');
const assert = require('assert');
const fs = require('fs');
const fs = require('fs');
const path = require('path');
const path = require('path');
@@ -87,10 +87,8 @@ t.test('the public vhost proxies the home, its files and exactly the developer-a
@@ -87,10 +87,8 @@ t.test('the public vhost proxies the home, its files and exactly the developer-a
assert.ok(!conf.includes('$proxy_add_x_forwarded_for'));
assert.ok(!conf.includes('$proxy_add_x_forwarded_for'));
});
});
-t.test('ai.openvibe.network answers 301 to the same path on ai.openvibe.services, and proxies nothing', () => {
- const conf = active('ai.openvibe.network.conf');
- assert.ok(!conf.includes('proxy_pass'), 'nothing is served under the old name');
- assert.strictEqual((conf.match(/return 301 https:\/\/ai\.openvibe\.services\$request_uri;/g) || []).length, 2, 'HTTP and HTTPS');
+t.test('the retired ai.openvibe.network address has no vhost (plan T6, 2026-10-10)', () => {
+ assert.ok(!fs.existsSync(path.join(__dirname, '..', 'deploy', 'nginx', 'ai.openvibe.network.conf')));
});
});
t.test('the CSPs let Cloudflare Web Analytics load and report (it injects its beacon on this zone)', async () => {
t.test('the CSPs let Cloudflare Web Analytics load and report (it injects its beacon on this zone)', async () => {