aicodeman 1.8.0 → 1.8.2
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/README.md +23 -6
- package/README.zh-CN.md +22 -5
- package/dist/config/webview-limits.d.ts +36 -0
- package/dist/config/webview-limits.d.ts.map +1 -0
- package/dist/config/webview-limits.js +40 -0
- package/dist/config/webview-limits.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/webview.d.ts +84 -0
- package/dist/types/webview.d.ts.map +1 -0
- package/dist/types/webview.js +21 -0
- package/dist/types/webview.js.map +1 -0
- package/dist/web/middleware/auth.d.ts.map +1 -1
- package/dist/web/middleware/auth.js +75 -3
- package/dist/web/middleware/auth.js.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.adc992cd.js +38 -0
- package/dist/web/public/app.adc992cd.js.br +0 -0
- package/dist/web/public/app.adc992cd.js.gz +0 -0
- package/dist/web/public/{constants.21a0a83e.js → constants.e7175b95.js} +3 -0
- package/dist/web/public/constants.e7175b95.js.br +0 -0
- package/dist/web/public/{constants.21a0a83e.js.gz → constants.e7175b95.js.gz} +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/i18n.4dcf1b87.js.gz +0 -0
- package/dist/web/public/image-input.ee16ad88.js.gz +0 -0
- package/dist/web/public/index.html +86 -12
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.63794d0b.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.3f91acef.js.gz +0 -0
- package/dist/web/public/mobile-handlers.bc2b8c1d.js.gz +0 -0
- package/dist/web/public/mobile.2ebdbb03.css +1 -0
- package/dist/web/public/mobile.2ebdbb03.css.br +0 -0
- package/dist/web/public/mobile.2ebdbb03.css.gz +0 -0
- package/dist/web/public/notification-manager.fca811fd.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/panels-ui.58582d4c.js.gz +0 -0
- package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
- package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
- package/dist/web/public/respawn-ui.2d249da9.js.gz +0 -0
- package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
- package/dist/web/public/{session-ui.713c8836.js → session-ui.fd39c53c.js} +2 -2
- package/dist/web/public/session-ui.fd39c53c.js.br +0 -0
- package/dist/web/public/session-ui.fd39c53c.js.gz +0 -0
- package/dist/web/public/{settings-ui.0259fbe8.js → settings-ui.478c8242.js} +2 -2
- package/dist/web/public/settings-ui.478c8242.js.br +0 -0
- package/dist/web/public/settings-ui.478c8242.js.gz +0 -0
- package/dist/web/public/styles.3f797179.css +1 -0
- package/dist/web/public/styles.3f797179.css.br +0 -0
- package/dist/web/public/styles.3f797179.css.gz +0 -0
- package/dist/web/public/subagent-windows.69b60c35.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/terminal-ui.2d582bf6.js +3 -0
- package/dist/web/public/terminal-ui.2d582bf6.js.br +0 -0
- package/dist/web/public/terminal-ui.2d582bf6.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
- package/dist/web/public/webview-tabs.js +445 -0
- package/dist/web/public/webview-tabs.js.br +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/routes/index.d.ts +1 -0
- package/dist/web/routes/index.d.ts.map +1 -1
- package/dist/web/routes/index.js +1 -0
- package/dist/web/routes/index.js.map +1 -1
- package/dist/web/routes/webview-routes.d.ts +50 -0
- package/dist/web/routes/webview-routes.d.ts.map +1 -0
- package/dist/web/routes/webview-routes.js +541 -0
- package/dist/web/routes/webview-routes.js.map +1 -0
- package/dist/web/schemas.d.ts +26 -0
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +34 -0
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +11 -5
- package/dist/web/server.js.map +1 -1
- package/dist/web/sse-events.d.ts +7 -1
- package/dist/web/sse-events.d.ts.map +1 -1
- package/dist/web/sse-events.js +8 -1
- package/dist/web/sse-events.js.map +1 -1
- package/dist/web/webview-proxy.d.ts +181 -0
- package/dist/web/webview-proxy.d.ts.map +1 -0
- package/dist/web/webview-proxy.js +491 -0
- package/dist/web/webview-proxy.js.map +1 -0
- package/dist/webview-capabilities.d.ts +55 -0
- package/dist/webview-capabilities.d.ts.map +1 -0
- package/dist/webview-capabilities.js +102 -0
- package/dist/webview-capabilities.js.map +1 -0
- package/dist/webview-store.d.ts +16 -0
- package/dist/webview-store.d.ts.map +1 -0
- package/dist/webview-store.js +34 -0
- package/dist/webview-store.js.map +1 -0
- package/package.json +11 -2
- package/dist/web/public/app.2e95c82d.js +0 -38
- package/dist/web/public/app.2e95c82d.js.br +0 -0
- package/dist/web/public/app.2e95c82d.js.gz +0 -0
- package/dist/web/public/constants.21a0a83e.js.br +0 -0
- package/dist/web/public/mobile.f2dcfa13.css +0 -1
- package/dist/web/public/mobile.f2dcfa13.css.br +0 -0
- package/dist/web/public/mobile.f2dcfa13.css.gz +0 -0
- package/dist/web/public/session-ui.713c8836.js.br +0 -0
- package/dist/web/public/session-ui.713c8836.js.gz +0 -0
- package/dist/web/public/settings-ui.0259fbe8.js.br +0 -0
- package/dist/web/public/settings-ui.0259fbe8.js.gz +0 -0
- package/dist/web/public/styles.d2f415e2.css +0 -1
- package/dist/web/public/styles.d2f415e2.css.br +0 -0
- package/dist/web/public/styles.d2f415e2.css.gz +0 -0
- package/dist/web/public/terminal-ui.9ea677e9.js +0 -3
- package/dist/web/public/terminal-ui.9ea677e9.js.br +0 -0
- package/dist/web/public/terminal-ui.9ea677e9.js.gz +0 -0
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Web tabs: saved dashboard URLs, plus the reverse proxy that makes
|
|
3
|
+
* them embeddable.
|
|
4
|
+
*
|
|
5
|
+
* Two distinct surfaces live here, and the split matters:
|
|
6
|
+
*
|
|
7
|
+
* 1. `/api/webviews/*`, ordinary authenticated CRUD, owner-scoped like every
|
|
8
|
+
* other resource, returning the `ApiResponse` envelope.
|
|
9
|
+
* 2. `/webview/:cap/*`, the proxy. NOT an API surface. It authenticates on an
|
|
10
|
+
* unguessable capability in the path instead of Codeman's session cookie, and
|
|
11
|
+
* is correspondingly exempt from the cookie and Origin checks in
|
|
12
|
+
* `middleware/auth.ts`. See `src/webview-capabilities.ts` for why a cookie
|
|
13
|
+
* cannot work here (sandboxed iframes are opaque-origin, so their requests are
|
|
14
|
+
* cross-site and arrive with `Origin: null`).
|
|
15
|
+
*
|
|
16
|
+
* The proxy is registered inside an ENCAPSULATED plugin scope with its own
|
|
17
|
+
* catch-all content-type parser. Fastify scopes parsers to the plugin that
|
|
18
|
+
* registers them, which is what lets the proxy forward raw request bodies
|
|
19
|
+
* upstream while the rest of the app keeps its JSON parsing (and, critically,
|
|
20
|
+
* keeps `text/plain` raw, auto-parsing that was a real CSRF hole once).
|
|
21
|
+
*
|
|
22
|
+
* Endpoints:
|
|
23
|
+
* GET /api/webviews
|
|
24
|
+
* POST /api/webviews
|
|
25
|
+
* PATCH /api/webviews/:id
|
|
26
|
+
* DELETE /api/webviews/:id
|
|
27
|
+
* POST /api/webviews/probe
|
|
28
|
+
* POST /api/webviews/:id/open
|
|
29
|
+
* ALL /webview/:cap/* (+ WebSocket upgrade on GET)
|
|
30
|
+
*/
|
|
31
|
+
import { randomUUID } from 'node:crypto';
|
|
32
|
+
import { Readable } from 'node:stream';
|
|
33
|
+
import { WebSocket as WsClient } from 'ws';
|
|
34
|
+
import { getDataDir } from '../../config/instance.js';
|
|
35
|
+
import { MAX_LIVE_WEBVIEW_FRAMES, MAX_WEBVIEWS, MAX_WEBVIEW_HTML_REWRITE_BYTES, MAX_WEBVIEW_SOCKETS, WEBVIEW_PROBE_TIMEOUT_MS, WEBVIEW_PROXY_PREFIX, WEBVIEW_UPSTREAM_TIMEOUT_MS, } from '../../config/webview-limits.js';
|
|
36
|
+
import { readWebviews, writeWebviews } from '../../webview-store.js';
|
|
37
|
+
import { webviewCapabilities } from '../../webview-capabilities.js';
|
|
38
|
+
import { ApiErrorCode, createErrorResponse } from '../../types.js';
|
|
39
|
+
import { AUTH_COOKIE_NAME } from '../middleware/auth.js';
|
|
40
|
+
import { canAccessOwned, getAuthUser, ownerFor, parseBody } from '../route-helpers.js';
|
|
41
|
+
import { WebviewCreateSchema, WebviewProbeSchema, WebviewUpdateSchema } from '../schemas.js';
|
|
42
|
+
import { SseEvent } from '../sse-events.js';
|
|
43
|
+
import { buildDownstreamResponseHeaders, buildProxyCorsHeaders, buildUpstreamRequestHeaders, capabilityFromReferer, extractFrameAncestors, isFramableCrossOrigin, isHtmlContentType, parseWebviewUrl, proxyPrefixFor, resolveUpstreamUrl, rewriteHtml, upstreamWebSocketUrl, } from '../webview-proxy.js';
|
|
44
|
+
/**
|
|
45
|
+
* Resolved per call rather than captured at module load. `getDataDir()` reads
|
|
46
|
+
* `CODEMAN_DATA_DIR` each time, so a lazy lookup keeps tests writing to a temp dir
|
|
47
|
+
* instead of the developer's real `~/.codeman/webviews.json`.
|
|
48
|
+
*/
|
|
49
|
+
function configDir() {
|
|
50
|
+
return getDataDir();
|
|
51
|
+
}
|
|
52
|
+
/** Live proxied WebSockets per webview id, so one dashboard cannot exhaust the socket budget. */
|
|
53
|
+
const socketCounts = new Map();
|
|
54
|
+
/** Serialize webview mutations: read-modify-write on a shared JSON file otherwise races. */
|
|
55
|
+
let writeChain = Promise.resolve();
|
|
56
|
+
function withWebviews(fn) {
|
|
57
|
+
const next = writeChain.then(async () => {
|
|
58
|
+
const list = await readWebviews(configDir());
|
|
59
|
+
return fn(list);
|
|
60
|
+
});
|
|
61
|
+
// Keep the chain alive even if this link rejects, or every later write deadlocks.
|
|
62
|
+
writeChain = next.catch(() => undefined);
|
|
63
|
+
return next;
|
|
64
|
+
}
|
|
65
|
+
export function registerWebviewRoutes(app, ctx) {
|
|
66
|
+
registerCrudRoutes(app, ctx);
|
|
67
|
+
registerProxyRoutes(app);
|
|
68
|
+
}
|
|
69
|
+
// ───────────────────────────── CRUD ─────────────────────────────
|
|
70
|
+
function registerCrudRoutes(app, ctx) {
|
|
71
|
+
app.get('/api/webviews', async (req) => {
|
|
72
|
+
const user = getAuthUser(req);
|
|
73
|
+
const all = await readWebviews(configDir());
|
|
74
|
+
const webviews = all.filter((w) => canAccessOwned(user, w.owner));
|
|
75
|
+
return { success: true, data: { webviews, maxLiveFrames: MAX_LIVE_WEBVIEW_FRAMES } };
|
|
76
|
+
});
|
|
77
|
+
app.post('/api/webviews', async (req, reply) => {
|
|
78
|
+
const input = parseBody(WebviewCreateSchema, req.body);
|
|
79
|
+
const owner = ownerFor(req);
|
|
80
|
+
const user = getAuthUser(req);
|
|
81
|
+
const created = await withWebviews(async (list) => {
|
|
82
|
+
const mine = list.filter((w) => canAccessOwned(user, w.owner));
|
|
83
|
+
if (mine.length >= MAX_WEBVIEWS)
|
|
84
|
+
return null;
|
|
85
|
+
const webview = {
|
|
86
|
+
id: randomUUID(),
|
|
87
|
+
name: input.name,
|
|
88
|
+
url: input.url,
|
|
89
|
+
icon: input.icon,
|
|
90
|
+
// Proxy is the safe default: it is the only mode that works for a plain-HTTP
|
|
91
|
+
// dashboard on an HTTPS Codeman, which is the common case.
|
|
92
|
+
embedMode: input.embedMode ?? 'proxy',
|
|
93
|
+
trusted: input.trusted ?? false,
|
|
94
|
+
owner,
|
|
95
|
+
createdAt: Date.now(),
|
|
96
|
+
};
|
|
97
|
+
list.push(webview);
|
|
98
|
+
await writeWebviews(configDir(), list);
|
|
99
|
+
return webview;
|
|
100
|
+
});
|
|
101
|
+
if (!created) {
|
|
102
|
+
return reply
|
|
103
|
+
.code(400)
|
|
104
|
+
.send(createErrorResponse(ApiErrorCode.INVALID_INPUT, `Webview limit reached (max ${MAX_WEBVIEWS})`));
|
|
105
|
+
}
|
|
106
|
+
ctx.broadcast(SseEvent.WebviewChanged, { action: 'created', id: created.id });
|
|
107
|
+
return { success: true, data: created };
|
|
108
|
+
});
|
|
109
|
+
app.patch('/api/webviews/:id', async (req, reply) => {
|
|
110
|
+
const input = parseBody(WebviewUpdateSchema, req.body);
|
|
111
|
+
const user = getAuthUser(req);
|
|
112
|
+
const { id } = req.params;
|
|
113
|
+
const updated = await withWebviews(async (list) => {
|
|
114
|
+
const index = list.findIndex((w) => w.id === id);
|
|
115
|
+
if (index === -1)
|
|
116
|
+
return 'not-found';
|
|
117
|
+
if (!canAccessOwned(user, list[index].owner))
|
|
118
|
+
return 'forbidden';
|
|
119
|
+
const next = { ...list[index], ...input };
|
|
120
|
+
list[index] = next;
|
|
121
|
+
await writeWebviews(configDir(), list);
|
|
122
|
+
return next;
|
|
123
|
+
});
|
|
124
|
+
if (updated === 'not-found') {
|
|
125
|
+
return reply.code(404).send(createErrorResponse(ApiErrorCode.NOT_FOUND, 'Webview not found'));
|
|
126
|
+
}
|
|
127
|
+
if (updated === 'forbidden') {
|
|
128
|
+
return reply.code(403).send(createErrorResponse(ApiErrorCode.FORBIDDEN, 'Not your webview'));
|
|
129
|
+
}
|
|
130
|
+
// Any edit invalidates the outstanding capability. Otherwise a token minted
|
|
131
|
+
// against the OLD url keeps proxying to it after the user repointed the tab.
|
|
132
|
+
webviewCapabilities.revokeWebview(id);
|
|
133
|
+
ctx.broadcast(SseEvent.WebviewChanged, { action: 'updated', id });
|
|
134
|
+
return { success: true, data: updated };
|
|
135
|
+
});
|
|
136
|
+
app.delete('/api/webviews/:id', async (req, reply) => {
|
|
137
|
+
const user = getAuthUser(req);
|
|
138
|
+
const { id } = req.params;
|
|
139
|
+
const result = await withWebviews(async (list) => {
|
|
140
|
+
const index = list.findIndex((w) => w.id === id);
|
|
141
|
+
if (index === -1)
|
|
142
|
+
return 'not-found';
|
|
143
|
+
if (!canAccessOwned(user, list[index].owner))
|
|
144
|
+
return 'forbidden';
|
|
145
|
+
list.splice(index, 1);
|
|
146
|
+
await writeWebviews(configDir(), list);
|
|
147
|
+
return 'deleted';
|
|
148
|
+
});
|
|
149
|
+
if (result === 'not-found') {
|
|
150
|
+
return reply.code(404).send(createErrorResponse(ApiErrorCode.NOT_FOUND, 'Webview not found'));
|
|
151
|
+
}
|
|
152
|
+
if (result === 'forbidden') {
|
|
153
|
+
return reply.code(403).send(createErrorResponse(ApiErrorCode.FORBIDDEN, 'Not your webview'));
|
|
154
|
+
}
|
|
155
|
+
webviewCapabilities.revokeWebview(id);
|
|
156
|
+
socketCounts.delete(id);
|
|
157
|
+
ctx.broadcast(SseEvent.WebviewChanged, { action: 'deleted', id });
|
|
158
|
+
return { success: true, data: { id } };
|
|
159
|
+
});
|
|
160
|
+
/**
|
|
161
|
+
* Reachability + framing probe for the editor's "Test" button.
|
|
162
|
+
*
|
|
163
|
+
* Runs from the SERVER, which is the network position the proxy will use, so a
|
|
164
|
+
* green result here means the proxy will actually work. Never throws upstream
|
|
165
|
+
* failures at the caller: an unreachable dashboard is a normal answer, not a 500.
|
|
166
|
+
*/
|
|
167
|
+
app.post('/api/webviews/probe', async (req) => {
|
|
168
|
+
const { url } = parseBody(WebviewProbeSchema, req.body);
|
|
169
|
+
return { success: true, data: await probeUrl(url) };
|
|
170
|
+
});
|
|
171
|
+
/**
|
|
172
|
+
* Mint the capability the iframe will load. Separate from GET /api/webviews so a
|
|
173
|
+
* capability exists only for dashboards actually opened, and so the TTL clock
|
|
174
|
+
* starts on open rather than on page load.
|
|
175
|
+
*/
|
|
176
|
+
app.post('/api/webviews/:id/open', async (req, reply) => {
|
|
177
|
+
const user = getAuthUser(req);
|
|
178
|
+
const { id } = req.params;
|
|
179
|
+
const webview = await withWebviews(async (list) => {
|
|
180
|
+
const index = list.findIndex((w) => w.id === id);
|
|
181
|
+
if (index === -1)
|
|
182
|
+
return 'not-found';
|
|
183
|
+
if (!canAccessOwned(user, list[index].owner))
|
|
184
|
+
return 'forbidden';
|
|
185
|
+
list[index] = { ...list[index], lastOpenedAt: Date.now() };
|
|
186
|
+
await writeWebviews(configDir(), list);
|
|
187
|
+
return list[index];
|
|
188
|
+
});
|
|
189
|
+
if (webview === 'not-found') {
|
|
190
|
+
return reply.code(404).send(createErrorResponse(ApiErrorCode.NOT_FOUND, 'Webview not found'));
|
|
191
|
+
}
|
|
192
|
+
if (webview === 'forbidden') {
|
|
193
|
+
return reply.code(403).send(createErrorResponse(ApiErrorCode.FORBIDDEN, 'Not your webview'));
|
|
194
|
+
}
|
|
195
|
+
// Direct mode has no capability to mint: the iframe loads the real URL.
|
|
196
|
+
if (webview.embedMode === 'direct') {
|
|
197
|
+
const data = { webview };
|
|
198
|
+
return { success: true, data };
|
|
199
|
+
}
|
|
200
|
+
const capability = webviewCapabilities.mint(webview.id, webview.owner);
|
|
201
|
+
const data = { webview, embedUrl: proxyPrefixFor(capability) };
|
|
202
|
+
return { success: true, data };
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
async function probeUrl(url) {
|
|
206
|
+
const target = parseWebviewUrl(url);
|
|
207
|
+
if (!target) {
|
|
208
|
+
return {
|
|
209
|
+
reachable: false,
|
|
210
|
+
framable: false,
|
|
211
|
+
recommendedMode: 'proxy',
|
|
212
|
+
reason: 'Invalid URL',
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
const response = await fetch(target.href, {
|
|
217
|
+
method: 'GET',
|
|
218
|
+
redirect: 'manual',
|
|
219
|
+
signal: AbortSignal.timeout(WEBVIEW_PROBE_TIMEOUT_MS),
|
|
220
|
+
});
|
|
221
|
+
// The body is irrelevant to the probe; release the socket rather than leak it.
|
|
222
|
+
await response.body?.cancel().catch(() => undefined);
|
|
223
|
+
const xFrameOptions = response.headers.get('x-frame-options') ?? undefined;
|
|
224
|
+
const csp = response.headers.get('content-security-policy') ?? undefined;
|
|
225
|
+
const frameAncestors = extractFrameAncestors(csp);
|
|
226
|
+
const framable = isFramableCrossOrigin(xFrameOptions, csp);
|
|
227
|
+
const isHttp = target.protocol === 'http:';
|
|
228
|
+
// Direct embedding is only viable for an HTTPS target that permits framing:
|
|
229
|
+
// an HTTPS Codeman page cannot embed http:// at all (mixed content).
|
|
230
|
+
const recommendedMode = !isHttp && framable ? 'direct' : 'proxy';
|
|
231
|
+
const reason = isHttp
|
|
232
|
+
? 'Plain HTTP: an HTTPS Codeman page cannot embed it directly, so it is proxied.'
|
|
233
|
+
: framable
|
|
234
|
+
? 'Reachable and allows framing: can be embedded directly.'
|
|
235
|
+
: 'Reachable but refuses framing, so it is proxied.';
|
|
236
|
+
return {
|
|
237
|
+
reachable: true,
|
|
238
|
+
status: response.status,
|
|
239
|
+
xFrameOptions,
|
|
240
|
+
frameAncestors,
|
|
241
|
+
framable,
|
|
242
|
+
recommendedMode,
|
|
243
|
+
reason,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
248
|
+
return {
|
|
249
|
+
reachable: false,
|
|
250
|
+
framable: false,
|
|
251
|
+
recommendedMode: 'proxy',
|
|
252
|
+
reason: `Server could not reach it: ${message}`,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// ───────────────────────────── Proxy ─────────────────────────────
|
|
257
|
+
function registerProxyRoutes(app) {
|
|
258
|
+
app.register(async (scope) => {
|
|
259
|
+
// Encapsulated to this plugin only. The proxy must relay request bodies
|
|
260
|
+
// BYTE-FOR-BYTE, so every parser is replaced with a pass-through that hands
|
|
261
|
+
// back the raw stream. Doing this on the root instance would break JSON
|
|
262
|
+
// routes and un-fix the text/plain CSRF hardening.
|
|
263
|
+
scope.removeAllContentTypeParsers();
|
|
264
|
+
scope.addContentTypeParser('*', (_req, payload, done) => done(null, payload));
|
|
265
|
+
// A single GET route serving both roles: `handler` for normal requests,
|
|
266
|
+
// `wsHandler` for upgrades. Registering them as two routes on one URL would
|
|
267
|
+
// collide.
|
|
268
|
+
scope.route({
|
|
269
|
+
method: 'GET',
|
|
270
|
+
url: `${WEBVIEW_PROXY_PREFIX}/:cap/*`,
|
|
271
|
+
handler: proxyHttp,
|
|
272
|
+
wsHandler: proxyWebSocket,
|
|
273
|
+
});
|
|
274
|
+
// HEAD is deliberately absent: Fastify's `exposeHeadRoutes` already derives a
|
|
275
|
+
// HEAD route from the GET above, and declaring it again is a startup error.
|
|
276
|
+
scope.route({
|
|
277
|
+
method: ['POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
|
|
278
|
+
url: `${WEBVIEW_PROXY_PREFIX}/:cap/*`,
|
|
279
|
+
handler: proxyHttp,
|
|
280
|
+
});
|
|
281
|
+
// `/webview/<cap>` with no trailing slash: redirect rather than serve, so the
|
|
282
|
+
// browser's notion of the base path ends in `/` and relative URLs in the
|
|
283
|
+
// dashboard's HTML resolve inside the prefix instead of one level above it.
|
|
284
|
+
scope.get(`${WEBVIEW_PROXY_PREFIX}/:cap`, (req, reply) => {
|
|
285
|
+
return reply.redirect(proxyPrefixFor(req.params.cap), 302);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/** Resolve a capability to its live webview record, or null. */
|
|
290
|
+
async function lookupCapability(capability) {
|
|
291
|
+
const record = webviewCapabilities.resolve(capability);
|
|
292
|
+
if (!record)
|
|
293
|
+
return null;
|
|
294
|
+
const list = await readWebviews(configDir());
|
|
295
|
+
const webview = list.find((w) => w.id === record.webviewId);
|
|
296
|
+
if (!webview)
|
|
297
|
+
return null;
|
|
298
|
+
// The capability is bound to the identity that minted it; an ownership change
|
|
299
|
+
// on the record must not leave a stale token working.
|
|
300
|
+
if (webview.owner !== record.owner)
|
|
301
|
+
return null;
|
|
302
|
+
return webview;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* ⚠ Every exit path RETURNS `reply.send(...)`.
|
|
306
|
+
*
|
|
307
|
+
* This handler is `async`, and Fastify resolves an async handler's promise as the
|
|
308
|
+
* response. `reply.send(stream)` followed by a bare `return` resolves to
|
|
309
|
+
* `undefined` before the stream has been consumed, and Fastify then answers with
|
|
310
|
+
* an EMPTY body: HTML (a synchronously-set string payload) survives it, every
|
|
311
|
+
* streamed asset comes back zero-length. Returning the reply is what tells Fastify
|
|
312
|
+
* the response is already owned by this handler.
|
|
313
|
+
*/
|
|
314
|
+
function proxyHttp(req, reply) {
|
|
315
|
+
return proxyRequest(req, reply, req.params.cap, req.params['*'] ?? '');
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Proxy one request to the dashboard behind `cap`, serving `wildcard` as the
|
|
319
|
+
* upstream path. Split out from the route handler so the 404 fallback (which has
|
|
320
|
+
* no route params) can reuse it.
|
|
321
|
+
*/
|
|
322
|
+
async function proxyRequest(req, reply, cap, wildcard) {
|
|
323
|
+
const webview = await lookupCapability(cap);
|
|
324
|
+
if (!webview) {
|
|
325
|
+
return reply.code(403).type('text/plain').send('Forbidden: unknown or expired webview capability');
|
|
326
|
+
}
|
|
327
|
+
// CORS is required even though the URL is on this host: a sandboxed dashboard is
|
|
328
|
+
// opaque-origin, so its fetch/XHR are cross-origin requests. See
|
|
329
|
+
// buildProxyCorsHeaders.
|
|
330
|
+
const cors = buildProxyCorsHeaders(typeof req.headers.origin === 'string' ? req.headers.origin : undefined, typeof req.headers['access-control-request-headers'] === 'string'
|
|
331
|
+
? req.headers['access-control-request-headers']
|
|
332
|
+
: undefined);
|
|
333
|
+
// Answer the preflight here rather than relaying it: the dashboard has no reason
|
|
334
|
+
// to know it is being framed, and most would reject an unexpected `Origin: null`.
|
|
335
|
+
if (req.method === 'OPTIONS' && req.headers['access-control-request-method']) {
|
|
336
|
+
for (const [key, value] of Object.entries(cors))
|
|
337
|
+
reply.header(key, value);
|
|
338
|
+
return reply.code(204).send();
|
|
339
|
+
}
|
|
340
|
+
const queryStart = req.url.indexOf('?');
|
|
341
|
+
const search = queryStart === -1 ? '' : req.url.slice(queryStart);
|
|
342
|
+
const upstream = resolveUpstreamUrl(webview.url, wildcard, search);
|
|
343
|
+
if (!upstream) {
|
|
344
|
+
return reply.code(400).type('text/plain').send('Bad Request: path escapes the dashboard origin');
|
|
345
|
+
}
|
|
346
|
+
const hasBody = req.method !== 'GET' && req.method !== 'HEAD';
|
|
347
|
+
const headers = buildUpstreamRequestHeaders(req.headers, upstream, {
|
|
348
|
+
forwardCookies: webview.trusted,
|
|
349
|
+
sessionCookieName: AUTH_COOKIE_NAME,
|
|
350
|
+
refererPath: typeof req.headers.referer === 'string' ? stripProxyPrefix(req.headers.referer, cap) : undefined,
|
|
351
|
+
});
|
|
352
|
+
let response;
|
|
353
|
+
try {
|
|
354
|
+
response = await fetch(upstream.href, {
|
|
355
|
+
method: req.method,
|
|
356
|
+
headers,
|
|
357
|
+
body: hasBody ? req.body : undefined,
|
|
358
|
+
// Required by undici whenever the body is a stream.
|
|
359
|
+
...(hasBody ? { duplex: 'half' } : {}),
|
|
360
|
+
// Redirects are rewritten into the proxy prefix instead of followed, so the
|
|
361
|
+
// browser's URL stays inside the frame and relative assets keep resolving.
|
|
362
|
+
redirect: 'manual',
|
|
363
|
+
signal: AbortSignal.timeout(WEBVIEW_UPSTREAM_TIMEOUT_MS),
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
catch (err) {
|
|
367
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
368
|
+
return reply.code(502).type('text/plain').send(`Dashboard unreachable: ${message}`);
|
|
369
|
+
}
|
|
370
|
+
const secureContext = req.protocol === 'https';
|
|
371
|
+
const { headers: outHeaders, setCookie, csp, } = buildDownstreamResponseHeaders(response.headers, response.headers.getSetCookie(), cap, upstream, secureContext);
|
|
372
|
+
reply.code(response.status);
|
|
373
|
+
for (const [key, value] of Object.entries(outHeaders))
|
|
374
|
+
reply.header(key, value);
|
|
375
|
+
// After the upstream headers, so ours win: an upstream ACAO would name the
|
|
376
|
+
// dashboard's own origin, not the opaque origin this frame actually has.
|
|
377
|
+
for (const [key, value] of Object.entries(cors))
|
|
378
|
+
reply.header(key, value);
|
|
379
|
+
for (const cookie of setCookie)
|
|
380
|
+
reply.header('set-cookie', cookie);
|
|
381
|
+
// registerSecurityHeaders already stamped Codeman's own `default-src 'self'`
|
|
382
|
+
// policy on this reply during onRequest. Left in place it breaks essentially
|
|
383
|
+
// every dashboard (inline scripts, CDN assets), so it is replaced by the
|
|
384
|
+
// upstream's own policy, or removed when the upstream had none.
|
|
385
|
+
if (csp)
|
|
386
|
+
reply.header('content-security-policy', csp);
|
|
387
|
+
else
|
|
388
|
+
reply.removeHeader('content-security-policy');
|
|
389
|
+
if (!response.body || req.method === 'HEAD') {
|
|
390
|
+
return reply.send();
|
|
391
|
+
}
|
|
392
|
+
const contentType = response.headers.get('content-type') ?? undefined;
|
|
393
|
+
const declaredLength = Number(response.headers.get('content-length') ?? '0');
|
|
394
|
+
const rewritable = isHtmlContentType(contentType) && declaredLength <= MAX_WEBVIEW_HTML_REWRITE_BYTES;
|
|
395
|
+
if (rewritable) {
|
|
396
|
+
// Buffer only HTML, only under the cap: `<base>` injection needs the whole
|
|
397
|
+
// document, and buffering an unbounded upstream body is a memory hazard.
|
|
398
|
+
const html = await response.text();
|
|
399
|
+
return reply.send(html.length <= MAX_WEBVIEW_HTML_REWRITE_BYTES ? rewriteHtml(html, cap) : html);
|
|
400
|
+
}
|
|
401
|
+
return reply.send(Readable.fromWeb(response.body));
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Last-resort handler for a dashboard asset requested with a ROOT-ABSOLUTE URL.
|
|
405
|
+
*
|
|
406
|
+
* `<base href>` fixes relative URLs and the HTML rewrite fixes `src`/`href`/`action`
|
|
407
|
+
* attributes, but neither can reach a URL built at runtime: `fetch('/api/data')`,
|
|
408
|
+
* `import('/chunk.js')`, `url(/img.png)` inside a stylesheet. Those arrive at
|
|
409
|
+
* Codeman's root and 404.
|
|
410
|
+
*
|
|
411
|
+
* The `Referer` identifies which dashboard asked, so the request can be routed to
|
|
412
|
+
* the right upstream. Wiring it into the 404 handler rather than a catch-all route
|
|
413
|
+
* is what keeps it contained: every real Codeman route matches first, and this only
|
|
414
|
+
* ever sees requests that were going to fail anyway.
|
|
415
|
+
*
|
|
416
|
+
* @returns true when the request was handled (caller must not also reply).
|
|
417
|
+
*/
|
|
418
|
+
export async function tryWebviewRefererFallback(req, reply) {
|
|
419
|
+
// Safe methods only. A write arriving here has already lost its raw body to the
|
|
420
|
+
// root instance's JSON parser, so it could not be relayed faithfully anyway.
|
|
421
|
+
if (req.method !== 'GET' && req.method !== 'HEAD')
|
|
422
|
+
return false;
|
|
423
|
+
const capability = capabilityFromReferer(typeof req.headers.referer === 'string' ? req.headers.referer : undefined);
|
|
424
|
+
if (!capability)
|
|
425
|
+
return false;
|
|
426
|
+
if (!webviewCapabilities.resolve(capability))
|
|
427
|
+
return false;
|
|
428
|
+
const path = req.url.split('?')[0].replace(/^\//, '');
|
|
429
|
+
await proxyRequest(req, reply, capability, path);
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
/** Turn a proxy-side Referer back into the upstream path it corresponds to. */
|
|
433
|
+
function stripProxyPrefix(referer, capability) {
|
|
434
|
+
try {
|
|
435
|
+
const url = new URL(referer);
|
|
436
|
+
const prefix = proxyPrefixFor(capability);
|
|
437
|
+
if (!url.pathname.startsWith(prefix))
|
|
438
|
+
return undefined;
|
|
439
|
+
return `/${url.pathname.slice(prefix.length)}${url.search}`;
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
return undefined;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// ─────────────────────────── WebSocket ───────────────────────────
|
|
446
|
+
/**
|
|
447
|
+
* Relay a WebSocket through to the dashboard.
|
|
448
|
+
*
|
|
449
|
+
* Live dashboards (Grafana, Home Assistant, Uptime Kuma) push over WebSocket, so
|
|
450
|
+
* without this leg they load but their realtime panels stay permanently empty.
|
|
451
|
+
*
|
|
452
|
+
* The upgrade is guarded on the capability, NOT on `Origin`: a sandboxed iframe is
|
|
453
|
+
* opaque-origin, so its upgrade arrives with `Origin: null`. The host allowlist
|
|
454
|
+
* still applies (it runs in the global onRequest hook), so DNS-rebinding
|
|
455
|
+
* protection is unaffected.
|
|
456
|
+
*/
|
|
457
|
+
function proxyWebSocket(socket, req) {
|
|
458
|
+
const { cap } = req.params;
|
|
459
|
+
void (async () => {
|
|
460
|
+
const webview = await lookupCapability(cap);
|
|
461
|
+
if (!webview) {
|
|
462
|
+
socket.close(4003, 'Forbidden');
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const live = socketCounts.get(webview.id) ?? 0;
|
|
466
|
+
if (live >= MAX_WEBVIEW_SOCKETS) {
|
|
467
|
+
socket.close(4008, 'Too many connections');
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const wildcard = req.params['*'] ?? '';
|
|
471
|
+
const queryStart = req.url.indexOf('?');
|
|
472
|
+
const search = queryStart === -1 ? '' : req.url.slice(queryStart);
|
|
473
|
+
const upstream = resolveUpstreamUrl(webview.url, wildcard, search);
|
|
474
|
+
if (!upstream) {
|
|
475
|
+
socket.close(4003, 'Forbidden');
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
socketCounts.set(webview.id, live + 1);
|
|
479
|
+
let released = false;
|
|
480
|
+
const release = () => {
|
|
481
|
+
if (released)
|
|
482
|
+
return;
|
|
483
|
+
released = true;
|
|
484
|
+
const count = socketCounts.get(webview.id) ?? 1;
|
|
485
|
+
if (count <= 1)
|
|
486
|
+
socketCounts.delete(webview.id);
|
|
487
|
+
else
|
|
488
|
+
socketCounts.set(webview.id, count - 1);
|
|
489
|
+
};
|
|
490
|
+
const protocols = req.headers['sec-websocket-protocol'];
|
|
491
|
+
const upstreamSocket = new WsClient(upstreamWebSocketUrl(upstream), protocols ? String(protocols).split(/,\s*/) : [], {
|
|
492
|
+
headers: {
|
|
493
|
+
origin: upstream.origin,
|
|
494
|
+
...(webview.trusted && req.headers.cookie ? { cookie: String(req.headers.cookie) } : {}),
|
|
495
|
+
},
|
|
496
|
+
handshakeTimeout: WEBVIEW_UPSTREAM_TIMEOUT_MS,
|
|
497
|
+
});
|
|
498
|
+
// Buffer anything the browser sends before the upstream handshake completes,
|
|
499
|
+
// rather than dropping it: a client that sends a subscribe frame immediately
|
|
500
|
+
// would otherwise sit connected and silent forever.
|
|
501
|
+
const pending = [];
|
|
502
|
+
let upstreamOpen = false;
|
|
503
|
+
upstreamSocket.on('open', () => {
|
|
504
|
+
upstreamOpen = true;
|
|
505
|
+
for (const message of pending)
|
|
506
|
+
upstreamSocket.send(message);
|
|
507
|
+
pending.length = 0;
|
|
508
|
+
});
|
|
509
|
+
socket.on('message', (data, isBinary) => {
|
|
510
|
+
const payload = isBinary ? data : data.toString();
|
|
511
|
+
if (upstreamOpen)
|
|
512
|
+
upstreamSocket.send(payload);
|
|
513
|
+
else if (pending.length < 64)
|
|
514
|
+
pending.push(payload);
|
|
515
|
+
});
|
|
516
|
+
upstreamSocket.on('message', (data, isBinary) => {
|
|
517
|
+
if (socket.readyState === socket.OPEN)
|
|
518
|
+
socket.send(isBinary ? data : data.toString());
|
|
519
|
+
});
|
|
520
|
+
// Paired close in both directions, so neither side is left half-open.
|
|
521
|
+
const closeBoth = (code, reason) => {
|
|
522
|
+
release();
|
|
523
|
+
// Codes outside 3000-4999 (and 1000/1001) are not valid to send onward.
|
|
524
|
+
const safeCode = code && code >= 3000 && code <= 4999 ? code : 1000;
|
|
525
|
+
if (socket.readyState === socket.OPEN)
|
|
526
|
+
socket.close(safeCode, reason);
|
|
527
|
+
if (upstreamSocket.readyState === WsClient.OPEN || upstreamSocket.readyState === WsClient.CONNECTING) {
|
|
528
|
+
upstreamSocket.close(safeCode, reason);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
socket.on('close', (code, reason) => closeBoth(code, reason?.toString()));
|
|
532
|
+
upstreamSocket.on('close', (code, reason) => closeBoth(code, reason?.toString()));
|
|
533
|
+
socket.on('error', () => closeBoth());
|
|
534
|
+
upstreamSocket.on('error', () => {
|
|
535
|
+
release();
|
|
536
|
+
if (socket.readyState === socket.OPEN)
|
|
537
|
+
socket.close(1011, 'Upstream error');
|
|
538
|
+
});
|
|
539
|
+
})();
|
|
540
|
+
}
|
|
541
|
+
//# sourceMappingURL=webview-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webview-routes.js","sourceRoot":"","sources":["../../../src/web/routes/webview-routes.ts"],"names":[],"mappings":"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"}
|
package/dist/web/schemas.d.ts
CHANGED
|
@@ -867,4 +867,30 @@ export declare const SearchQuerySchema: z.ZodObject<{
|
|
|
867
867
|
types: z.ZodOptional<z.ZodString>;
|
|
868
868
|
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
869
869
|
}, z.core.$strip>;
|
|
870
|
+
/** POST /api/webviews */
|
|
871
|
+
export declare const WebviewCreateSchema: z.ZodObject<{
|
|
872
|
+
name: z.ZodString;
|
|
873
|
+
url: z.ZodString;
|
|
874
|
+
icon: z.ZodOptional<z.ZodString>;
|
|
875
|
+
embedMode: z.ZodOptional<z.ZodEnum<{
|
|
876
|
+
proxy: "proxy";
|
|
877
|
+
direct: "direct";
|
|
878
|
+
}>>;
|
|
879
|
+
trusted: z.ZodOptional<z.ZodBoolean>;
|
|
880
|
+
}, z.core.$strip>;
|
|
881
|
+
/** PATCH /api/webviews/:id, partial update. */
|
|
882
|
+
export declare const WebviewUpdateSchema: z.ZodObject<{
|
|
883
|
+
name: z.ZodOptional<z.ZodString>;
|
|
884
|
+
url: z.ZodOptional<z.ZodString>;
|
|
885
|
+
icon: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
886
|
+
embedMode: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
|
|
887
|
+
proxy: "proxy";
|
|
888
|
+
direct: "direct";
|
|
889
|
+
}>>>;
|
|
890
|
+
trusted: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
|
|
891
|
+
}, z.core.$strip>;
|
|
892
|
+
/** POST /api/webviews/probe: reachability + framing check for the editor's Test button. */
|
|
893
|
+
export declare const WebviewProbeSchema: z.ZodObject<{
|
|
894
|
+
url: z.ZodString;
|
|
895
|
+
}, z.core.$strip>;
|
|
870
896
|
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/web/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/web/schemas.ts"],"names":[],"mappings":"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"}
|