@pleri/olam-cli 0.1.41 → 0.1.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/image-digests.json +2 -2
- package/host-cp/src/server.mjs +31 -1
- package/package.json +1 -1
package/dist/image-digests.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"auth": "sha256:4e2ea22c5ef026ecf7b10892fbe381384b32e83636962d86d9ab1fc572972f8e",
|
|
3
3
|
"devbox": "sha256:9363a1979d7df0ed2b2c964c183ba3e739383c146416f27b1ceb976f64648fd9",
|
|
4
|
-
"host-cp": "sha256:
|
|
4
|
+
"host-cp": "sha256:29d2e544db7fabae259a0311a76ff367ee5e2ca5f48e9640ebefaf3c5997bda3",
|
|
5
5
|
"$schema_version": 1,
|
|
6
|
-
"$published_version": "0.1.
|
|
6
|
+
"$published_version": "0.1.42",
|
|
7
7
|
"$registry": "ghcr.io/pleri"
|
|
8
8
|
}
|
package/host-cp/src/server.mjs
CHANGED
|
@@ -2155,7 +2155,37 @@ let _spaCacheMtime = 0;
|
|
|
2155
2155
|
// would 404 through host-cp returning the SPA shell — observed during
|
|
2156
2156
|
// M5 dogfood: clicking Dispatch on /world/<id> hit /dispatch directly,
|
|
2157
2157
|
// host-cp had no handler, and the SPA got HTML back instead of JSON.
|
|
2158
|
-
|
|
2158
|
+
// SPA bootstrap script — runs INLINE before any other script tag so it
|
|
2159
|
+
// can wrap window.fetch / window.EventSource before the SPA bundle loads.
|
|
2160
|
+
//
|
|
2161
|
+
// Three responsibilities:
|
|
2162
|
+
//
|
|
2163
|
+
// (1) Cookie sync: read /api/bootstrap synchronously to seed
|
|
2164
|
+
// `olam_host_cp_token`. The SPA's fetch calls then carry the
|
|
2165
|
+
// cookie automatically.
|
|
2166
|
+
//
|
|
2167
|
+
// (2) Path rewriting: `fetch('/session/<id>/state')` and similar
|
|
2168
|
+
// host-native short URLs get rewritten to the world-scoped form
|
|
2169
|
+
// `/api/world/<wid>/...` so host-cp's path-segment routing
|
|
2170
|
+
// dispatches them to the right per-world CP. EventSource gets
|
|
2171
|
+
// the same treatment for `/api/stream`, etc.
|
|
2172
|
+
//
|
|
2173
|
+
// (3) Auth-recovery: when a fetch returns 401 (the canonical signal
|
|
2174
|
+
// that the operator's cookie is stale — e.g. after an
|
|
2175
|
+
// `olam host-cp stop && start` rotates the token), re-read
|
|
2176
|
+
// /api/bootstrap. If the token changed, write the fresh cookie
|
|
2177
|
+
// and `location.reload()`. The SPA gets a clean restart with
|
|
2178
|
+
// the new auth context. This avoids the dogfood class where a
|
|
2179
|
+
// host-cp restart left the dashboard's readiness ladder stuck
|
|
2180
|
+
// at "Created" because the SPA's state poll silently 401'd and
|
|
2181
|
+
// no UI cue suggested a hard-reload.
|
|
2182
|
+
//
|
|
2183
|
+
// Guards against reload storms: a single `reloading` flag in the
|
|
2184
|
+
// closure prevents N concurrent 401s from triggering N reloads,
|
|
2185
|
+
// and the token-comparison check skips reload when the cookie
|
|
2186
|
+
// already matches (so non-rotation 401s — e.g. genuine auth
|
|
2187
|
+
// failures — don't cause a refresh loop).
|
|
2188
|
+
const BOOTSTRAP_SCRIPT = `<script>(function(){function ck(){var m=document.cookie.match(/olam_host_cp_token=([^;]+)/);return m?m[1]:'';}function sw(t){document.cookie='olam_host_cp_token='+t+'; path=/; samesite=strict';}try{var x=new XMLHttpRequest();x.open('GET','/api/bootstrap',false);x.send();if(x.status===200){var d=JSON.parse(x.responseText);sw(d.token);}}catch(e){console.error('[host-cp bootstrap]',e);}var reloading=false;function recover(){if(reloading)return;try{var x=new XMLHttpRequest();x.open('GET','/api/bootstrap',false);x.send();if(x.status===200){var d=JSON.parse(x.responseText);if(d.token&&ck()!==d.token){reloading=true;sw(d.token);console.warn('[host-cp auth recover] token rotated; reloading');location.reload();}}}catch(e){console.error('[host-cp auth recover]',e);}}var HN=['/api/bootstrap','/api/worlds','/api/projects','/api/workspaces','/api/workspaces/match','/api/auth','/health'];var WP=['/api/','/session/','/hooks/','/dispatch','/lanes','/codex/','/review/'];function sr(p){if(typeof p!=='string')return false;if(p.startsWith('/api/world/'))return false;for(var i=0;i<HN.length;i++){var n=HN[i];if(p===n||p.startsWith(n+'?')||p.startsWith(n+'/'))return false;}for(var j=0;j<WP.length;j++){var w=WP[j];if(p===w||p===w.replace(/\\/$/,'')||p.startsWith(w)||p.startsWith(w.replace(/\\/$/,'')+'?')||p.startsWith(w.replace(/\\/$/,'')+'/'))return true;}return false;}function wid(){var p=location.pathname;var m=p.match(/^\\/(world|inbox)\\/([^/?#]+)/);if(m)return m[2];if(/^\\/(?:worlds?|workspaces?|world|sandbox|inbox|plan|design|assets|api|health|favicon)($|\\/|\\?)/.test(p))return null;var r=p.match(/^\\/([a-z][a-z0-9-]+)(?:\\/|$|\\?)/);return r?r[1]:null;}function rw(p){var w=wid();return w?'/api/world/'+w+p:p;}var of=window.fetch.bind(window);window.fetch=function(input,init){var pr;if(typeof input==='string'&&sr(input))pr=of(rw(input),init);else if(input&&typeof input.url==='string'&&sr(input.url))pr=of(new Request(rw(input.url),input),init);else pr=of(input,init);return pr.then(function(res){if(res&&res.status===401)recover();return res;});};var OE=window.EventSource;if(OE){window.EventSource=function(u,i){var s=u;if(typeof s==='string'&&sr(s))s=rw(s);var es=new OE(s,i);es.addEventListener('error',function(){if(es.readyState===OE.CLOSED)recover();});return es;};window.EventSource.prototype=OE.prototype;window.EventSource.CONNECTING=OE.CONNECTING;window.EventSource.OPEN=OE.OPEN;window.EventSource.CLOSED=OE.CLOSED;}})();</script>`;
|
|
2159
2189
|
|
|
2160
2190
|
async function renderSpaShell(filePath) {
|
|
2161
2191
|
const stat = fs.statSync(filePath);
|