@danieltmn/openbridge 0.3.0 → 0.5.0
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/CHANGELOG.md +46 -0
- package/README.md +116 -32
- package/docs/ARCHITECTURE.md +56 -11
- package/package.json +2 -1
- package/src/auth.js +44 -23
- package/src/bridge/bridge.js +44 -5
- package/src/cli.js +194 -9
- package/src/config.js +74 -4
- package/src/web/assets/app.js +142 -63
- package/src/web/assets/manifest.webmanifest +2 -0
- package/src/web/assets/sw.js +1 -1
- package/src/web/routes.js +48 -14
- package/src/web/server.js +7 -0
- package/src/web/templates/chat.html +14 -2
- package/src/web/templates/login.html +7 -3
package/src/web/server.js
CHANGED
|
@@ -70,6 +70,13 @@ function securityHeaders(res) {
|
|
|
70
70
|
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
71
71
|
res.setHeader('Referrer-Policy', 'no-referrer');
|
|
72
72
|
res.setHeader('X-Frame-Options', 'DENY');
|
|
73
|
+
// La app usa scripts/estilos inline (templates) y data: para imagenes
|
|
74
|
+
// adjuntas. Igual bloquea origenes externos, frames y objetos.
|
|
75
|
+
res.setHeader('Content-Security-Policy',
|
|
76
|
+
"default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; "
|
|
77
|
+
+ "script-src 'self' 'unsafe-inline'; connect-src 'self'; worker-src 'self'; "
|
|
78
|
+
+ "manifest-src 'self'; object-src 'none'; base-uri 'none'; "
|
|
79
|
+
+ "frame-ancestors 'none'; form-action 'self'");
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
async function handle(app, req, res) {
|
|
@@ -280,6 +280,11 @@
|
|
|
280
280
|
text-align: center;
|
|
281
281
|
border: 1px solid var(--border);
|
|
282
282
|
}
|
|
283
|
+
#sidebar .footer .userbadge {
|
|
284
|
+
flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
285
|
+
color: var(--muted); font-size: 12px;
|
|
286
|
+
}
|
|
287
|
+
#sidebar .footer .userbadge.admin { color: var(--accent); }
|
|
283
288
|
#scrim {
|
|
284
289
|
display: none;
|
|
285
290
|
position: fixed; inset: 0;
|
|
@@ -1198,13 +1203,17 @@
|
|
|
1198
1203
|
<button data-view="preview" type="button" title="Vista previa del proyecto (túnel)">preview</button>
|
|
1199
1204
|
<button data-view="procs" type="button" title="Procesos de la sesión">procs</button>
|
|
1200
1205
|
<button data-view="changes" type="button" title="Cambios del proyecto (git)">cambios</button>
|
|
1206
|
+
<button data-view="mcp" type="button" title="Servidores MCP de opencode">mcp</button>
|
|
1201
1207
|
</div>
|
|
1202
1208
|
<div class="footer">
|
|
1203
1209
|
<div class="row" id="bridgeStatusRow">
|
|
1204
1210
|
<span class="dot" id="bridgeDot"></span>
|
|
1205
1211
|
<span id="bridgeStatusText">puente: desconocido</span>
|
|
1206
1212
|
</div>
|
|
1207
|
-
<
|
|
1213
|
+
<div class="row">
|
|
1214
|
+
<span class="userbadge" id="userBadge" title="sesión actual">{{USER_NAME}}</span>
|
|
1215
|
+
<a class="logout" href="logout.php">salir</a>
|
|
1216
|
+
</div>
|
|
1208
1217
|
</div>
|
|
1209
1218
|
<div class="resizer" id="sbResizer" title="Arrastrá para ajustar · doble clic para restablecer"></div>
|
|
1210
1219
|
</aside>
|
|
@@ -1277,6 +1286,7 @@
|
|
|
1277
1286
|
<div id="viewPreview" class="view" style="display:none"></div>
|
|
1278
1287
|
<div id="viewProcs" class="view" style="display:none"></div>
|
|
1279
1288
|
<div id="viewChanges" class="view" style="display:none"></div>
|
|
1289
|
+
<div id="viewMcp" class="view" style="display:none"></div>
|
|
1280
1290
|
|
|
1281
1291
|
<footer id="statusbar">
|
|
1282
1292
|
<span class="dot" id="sbDot"></span>
|
|
@@ -1344,7 +1354,9 @@
|
|
|
1344
1354
|
themes: {{THEMES_JSON}},
|
|
1345
1355
|
sseDisabled: {{SSE_DISABLED}},
|
|
1346
1356
|
pushEnabled: {{PUSH_ENABLED}},
|
|
1347
|
-
pushKey: "{{PUSH_KEY}}"
|
|
1357
|
+
pushKey: "{{PUSH_KEY}}",
|
|
1358
|
+
userName: "{{USER_NAME}}",
|
|
1359
|
+
userRole: "{{USER_ROLE}}"
|
|
1348
1360
|
};
|
|
1349
1361
|
</script>
|
|
1350
1362
|
<script src="app.js?v={{APPJS_VER}}" defer></script>
|
|
@@ -89,12 +89,12 @@
|
|
|
89
89
|
(function () {
|
|
90
90
|
var knownThemes = {{THEMES_JSON}};
|
|
91
91
|
var params = new URLSearchParams(location.search);
|
|
92
|
-
var cookie = document.cookie.match(/(?:^|;\s*)ocx_theme=([^;]+)/);
|
|
92
|
+
var cookie = document.cookie.match(/(?:^|;\s*)ob_theme=([^;]+)/) || document.cookie.match(/(?:^|;\s*)ocx_theme=([^;]+)/);
|
|
93
93
|
var saved = (params.get('theme') || (cookie && decodeURIComponent(cookie[1])) || document.body.getAttribute('data-theme') || 'terminal');
|
|
94
94
|
if (knownThemes.indexOf(saved) === -1) saved = 'terminal';
|
|
95
95
|
document.body.setAttribute('data-theme', saved);
|
|
96
96
|
document.getElementById('themeStylesheet').setAttribute('href', 'themes/' + saved + '.css');
|
|
97
|
-
document.cookie = '
|
|
97
|
+
document.cookie = 'ob_theme=' + encodeURIComponent(saved) + ';path=/;max-age=' + (60 * 60 * 24 * 365) + ';SameSite=Lax';
|
|
98
98
|
window.addEventListener('load', function () {
|
|
99
99
|
var bg = getComputedStyle(document.documentElement).getPropertyValue('--bg').trim();
|
|
100
100
|
if (bg) document.getElementById('themeColor').setAttribute('content', bg);
|
|
@@ -111,7 +111,11 @@
|
|
|
111
111
|
<input type="hidden" name="csrf" value="{{CSRF}}">
|
|
112
112
|
<label class="field">
|
|
113
113
|
<span class="prompt">❯</span>
|
|
114
|
-
<input type="
|
|
114
|
+
<input type="text" id="username" name="username" placeholder="usuario" required autofocus autocomplete="username" value="{{USER_PREFILL}}">
|
|
115
|
+
</label>
|
|
116
|
+
<label class="field">
|
|
117
|
+
<span class="prompt">❯</span>
|
|
118
|
+
<input type="password" id="password" name="password" placeholder="contraseña" required autocomplete="current-password">
|
|
115
119
|
<button type="button" class="peek" id="btnPeek" aria-label="Mostrar u ocultar contraseña" tabindex="-1">👁</button>
|
|
116
120
|
</label>
|
|
117
121
|
<label class="keep" for="keep">
|