@1agh/maude 0.53.1 → 0.53.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/apps/studio/bin/screenshot.sh +131 -15
- package/apps/studio/canvas-build-sandbox.ts +385 -0
- package/apps/studio/canvas-build-worker.ts +85 -0
- package/apps/studio/client/app.jsx +112 -8
- package/apps/studio/client/canvas-url.js +7 -0
- package/apps/studio/client/panels/SettingsPanel.jsx +32 -12
- package/apps/studio/client/report-bug.jsx +125 -30
- package/apps/studio/client/styles/4-components-maude.css +5 -0
- package/apps/studio/client/styles/4-components.css +35 -0
- package/apps/studio/dist/client.bundle.js +831 -831
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/http.ts +239 -20
- package/apps/studio/paths.ts +8 -0
- package/apps/studio/server.ts +102 -36
- package/apps/studio/test/canvas-build-sandbox.test.ts +69 -0
- package/apps/studio/test/canvas-origin-gate.test.ts +5 -0
- package/apps/studio/test/canvas-url.test.ts +26 -0
- package/apps/studio/test/cloud-session-role.test.ts +131 -0
- package/apps/studio/test/cloud-shell-surfaces.test.ts +90 -0
- package/apps/studio/test/config-projection.test.ts +104 -0
- package/apps/studio/test/read-only-gate.test.ts +50 -0
- package/apps/studio/test/workspace-containment.test.ts +90 -11
- package/apps/studio/whats-new.json +11 -2
- package/apps/studio/workspace-mode.ts +161 -28
- package/apps/studio/ws.ts +30 -0
- package/package.json +8 -8
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./whats-new.schema.json",
|
|
3
3
|
"entries": [
|
|
4
|
+
{
|
|
5
|
+
"id": "bug-reports-see-the-maude-window",
|
|
6
|
+
"version": "0.53.2",
|
|
7
|
+
"kind": "improvement",
|
|
8
|
+
"title": "Bug reports now show the Maude window",
|
|
9
|
+
"summary": "Report a bug used to attach only the artboard, so anything wrong with Maude itself — the menus, the sidebar, a panel — was never in the picture. It now captures the whole window too, and you can attach your own screenshot for whatever a fresh capture can't show, like an open menu or a stuck spinner.",
|
|
10
|
+
"surface": "design-ui",
|
|
11
|
+
"date": "2026-08-03"
|
|
12
|
+
},
|
|
4
13
|
{
|
|
5
14
|
"id": "open-your-project-in-a-browser",
|
|
6
15
|
"version": "0.53.0",
|
|
7
16
|
"date": "2026-08-02",
|
|
8
17
|
"kind": "feature",
|
|
9
|
-
"title": "Open your project in a browser —
|
|
10
|
-
"summary": "Send a teammate a link and they open the
|
|
18
|
+
"title": "Open your project in a browser — early access",
|
|
19
|
+
"summary": "Send a teammate a link and they open the project in their browser, signed in with their Maude account and with the rights their role gives them. This first release shows a simplified view: the full Maude Studio — Files, Layers, Inspector, search — and your project's own images and fonts are coming next.",
|
|
11
20
|
"surface": "design-ui"
|
|
12
21
|
},
|
|
13
22
|
{
|
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
// Workspace mode + the containment invariant's first enforcement point.
|
|
2
2
|
//
|
|
3
|
-
// DDR-193
|
|
3
|
+
// DDR-193 stated the invariant, and Cloud Phase 25 A0 amended what a cell does
|
|
4
|
+
// under it. The current wording (DDR-209 A′1) is:
|
|
4
5
|
//
|
|
5
|
-
// > No tenant-authored TSX is ever
|
|
6
|
-
// > A cell
|
|
7
|
-
// > canvas
|
|
8
|
-
// >
|
|
6
|
+
// > No tenant-authored TSX is ever EVALUATED by vendor-operated compute.
|
|
7
|
+
// > A cell syncs, keeps git history, stores assets, and BUILDS a member's own
|
|
8
|
+
// > canvas in a bounded sandbox. The member's browser is what evaluates.
|
|
9
|
+
// > Nothing here renders, and no browser enters the image.
|
|
9
10
|
//
|
|
10
11
|
// and states how it is kept: "enforced, not asserted — a boot-assert in the cell
|
|
11
12
|
// image plus a CI grep gate." This module is the boot-assert. The grep gate is
|
|
12
13
|
// `scripts/check-containment.sh`.
|
|
13
14
|
//
|
|
15
|
+
// THE TEST IS EVALUATION, NOT THE SERVING OF BYTES. That distinction is the
|
|
16
|
+
// whole of DDR-209 A′1, and it is load-bearing in both directions. It still
|
|
17
|
+
// catches the thumbnail endpoint someone adds in 2027 (which would evaluate). It
|
|
18
|
+
// stops mis-catching a static HTML harness with a strict CSP (which does not) —
|
|
19
|
+
// and mis-catching it is what forced Phase 25 to hand-roll a second, poorer
|
|
20
|
+
// studio rather than serve the real one.
|
|
21
|
+
//
|
|
14
22
|
// WHY A BOOT-ASSERT AND NOT A CODE REVIEW RULE. Every canvas is code the tenant
|
|
15
23
|
// wrote. The moment vendor compute evaluates it, an anonymous signup has
|
|
16
24
|
// arbitrary code execution inside our perimeter, next to other tenants' designs
|
|
17
25
|
// and the control plane's credentials. A convention protects that for exactly as
|
|
18
26
|
// long as everyone remembers it; a process that refuses to start does not
|
|
19
|
-
// forget.
|
|
20
|
-
// purpose" — it is "someone adds a thumbnail endpoint in 2027 without knowing
|
|
21
|
-
// this line exists."
|
|
27
|
+
// forget.
|
|
22
28
|
//
|
|
23
29
|
// It fails CLOSED and LOUD: the cell refuses to boot, naming the exact surfaces
|
|
24
30
|
// that broke it. A cell that will not start is a page; a cell that quietly
|
|
@@ -36,6 +42,15 @@ export function isWorkspaceMode(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
|
36
42
|
*
|
|
37
43
|
* These are prefixes: `/_api/export-jobs` is caught by `/_api/export` and that
|
|
38
44
|
* is intended — a variant of a forbidden surface is still forbidden.
|
|
45
|
+
*
|
|
46
|
+
* TWO KINDS OF ENTRY LIVE HERE, and both belong:
|
|
47
|
+
*
|
|
48
|
+
* 1. surfaces that EVALUATE tenant content on our compute (export, photo-edit);
|
|
49
|
+
* 2. surfaces that hold, spend or reveal a SECRET on our compute — a provider
|
|
50
|
+
* key, the operator's GitHub token, the user's own `claude` session, the
|
|
51
|
+
* process log. DDR-123's "claude never on our infra" is only a fact while
|
|
52
|
+
* these are unreachable, and Cloud Phase 27 D1 is where they stop being in
|
|
53
|
+
* the image at all. Until then, unreachable is the floor, not the ceiling.
|
|
39
54
|
*/
|
|
40
55
|
export const FORBIDDEN_ROUTE_PREFIXES: ReadonlyArray<{ prefix: string; why: string }> =
|
|
41
56
|
Object.freeze([
|
|
@@ -52,17 +67,84 @@ export const FORBIDDEN_ROUTE_PREFIXES: ReadonlyArray<{ prefix: string; why: stri
|
|
|
52
67
|
why: 'media generation runs tenant-authored prompts against a provider key held here',
|
|
53
68
|
},
|
|
54
69
|
{
|
|
55
|
-
prefix: '/
|
|
56
|
-
why: 'the
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
prefix: '/_canvas-runtime',
|
|
60
|
-
why: 'serving the canvas runtime only makes sense if something here renders a canvas',
|
|
70
|
+
prefix: '/_api/shell-shot',
|
|
71
|
+
why: 'the shell screenshot spawns a headless browser against the studio — the same evaluation `/_api/export` is forbidden for',
|
|
61
72
|
},
|
|
62
73
|
{
|
|
63
74
|
prefix: '/_ws/acp',
|
|
64
75
|
why: 'the ACP bridge spawns the user’s own `claude` and can drive file edits (DDR-123 is desktop-only)',
|
|
65
76
|
},
|
|
77
|
+
// ---- Cloud Phase 27 D1 — the secret-bearing surfaces, named at last ----
|
|
78
|
+
{
|
|
79
|
+
prefix: '/_api/acp',
|
|
80
|
+
why: 'the ACP surface drives the user’s own `claude` session; a cell must not hold one (DDR-123)',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
prefix: '/_api/claude',
|
|
84
|
+
why: 'installing or signing in to `claude` from a cell would put a user’s subscription on our infra (DDR-123)',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
prefix: '/_api/cloud',
|
|
88
|
+
why: 'cloud sign-in mints and stores an account session — a cell IS the cloud, it must not be a client of it',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
prefix: '/_api/github',
|
|
92
|
+
why: 'the GitHub lane spends an operator credential; a cell asks the control plane, it never holds one (DDR-201)',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
prefix: '/_api/hub',
|
|
96
|
+
why: 'hub linking rewrites which server owns this project — a cell must not repoint itself',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
prefix: '/_api/debug-bundle',
|
|
100
|
+
why: 'the diagnostic bundle reads this process’s logs, where every cell secret has had a chance to appear',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
prefix: '/_api/design',
|
|
104
|
+
why: 'design-system init shells out to the CLI on our compute against tenant-chosen input',
|
|
105
|
+
},
|
|
106
|
+
]);
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Routes a cell MAY serve, but only while the contract that makes them safe is
|
|
110
|
+
* armed. DDR-209 A′1.
|
|
111
|
+
*
|
|
112
|
+
* These are NOT a softer forbidden list. A forbidden route is absent; a
|
|
113
|
+
* sandboxed route is PRESENT AND ATTESTED — the boot-assert refuses to start
|
|
114
|
+
* when one of them is reachable and `sandboxArmed` is false, which is a check
|
|
115
|
+
* the old list could not make because the route never existed to check.
|
|
116
|
+
*
|
|
117
|
+
* What they are, precisely:
|
|
118
|
+
*
|
|
119
|
+
* `/_canvas-shell` a static HTML harness with a strict CSP. The cell emits
|
|
120
|
+
* a string; the MEMBER'S BROWSER mounts and executes. The
|
|
121
|
+
* old entry's reason ("the surface that mounts and
|
|
122
|
+
* executes a canvas module") described the browser's job,
|
|
123
|
+
* not ours.
|
|
124
|
+
* `/_canvas-runtime` pre-built VENDOR bundles (React, motion) compiled from
|
|
125
|
+
* our own source at image build. Not one tenant byte, and
|
|
126
|
+
* serving them evaluates nothing. The old entry's reason
|
|
127
|
+
* ("only makes sense if something here renders") is the
|
|
128
|
+
* premise Phase 25 A0 replaced: it makes sense because the
|
|
129
|
+
* browser renders.
|
|
130
|
+
*
|
|
131
|
+
* THE CONTRACT (Cloud Phase 25 A1, unchanged and still CI-asserted): the build
|
|
132
|
+
* that turns a canvas into that module runs in its OWN process, with an EMPTY
|
|
133
|
+
* environment, an import allowlist, a wall-clock deadline and an RSS ceiling.
|
|
134
|
+
* Serving the shell without that armed would mean building tenant source in the
|
|
135
|
+
* cell's main process, next to HUB_SECRET — so the assert treats an unarmed
|
|
136
|
+
* sandbox exactly like a forbidden route.
|
|
137
|
+
*/
|
|
138
|
+
export const SANDBOXED_ROUTE_PREFIXES: ReadonlyArray<{ prefix: string; why: string }> =
|
|
139
|
+
Object.freeze([
|
|
140
|
+
{
|
|
141
|
+
prefix: '/_canvas-shell',
|
|
142
|
+
why: 'the canvas shell is a static harness the BROWSER evaluates — permitted only while the build sandbox is armed',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
prefix: '/_canvas-runtime',
|
|
146
|
+
why: 'the runtime bundles are vendor code — permitted only while the build sandbox is armed',
|
|
147
|
+
},
|
|
66
148
|
]);
|
|
67
149
|
|
|
68
150
|
/**
|
|
@@ -78,9 +160,18 @@ export const FORBIDDEN_MODULES: ReadonlyArray<string> = Object.freeze([
|
|
|
78
160
|
'puppeteer-core',
|
|
79
161
|
]);
|
|
80
162
|
|
|
163
|
+
function matches(route: string, prefix: string): boolean {
|
|
164
|
+
return route === prefix || route.startsWith(prefix);
|
|
165
|
+
}
|
|
166
|
+
|
|
81
167
|
/** True when `route` is (or starts with) a forbidden prefix. */
|
|
82
168
|
export function isForbiddenRoute(route: string): boolean {
|
|
83
|
-
return FORBIDDEN_ROUTE_PREFIXES.some((f) => route
|
|
169
|
+
return FORBIDDEN_ROUTE_PREFIXES.some((f) => matches(route, f.prefix));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** True when `route` is one a cell may serve only while the sandbox is armed. */
|
|
173
|
+
export function isSandboxedRoute(route: string): boolean {
|
|
174
|
+
return SANDBOXED_ROUTE_PREFIXES.some((f) => matches(route, f.prefix));
|
|
84
175
|
}
|
|
85
176
|
|
|
86
177
|
/**
|
|
@@ -115,25 +206,38 @@ export interface ContainmentReport {
|
|
|
115
206
|
routes: Array<{ route: string; prefix: string; why: string }>;
|
|
116
207
|
/** Forbidden modules that resolve in this process. */
|
|
117
208
|
modules: string[];
|
|
209
|
+
/** Sandboxed routes that are reachable while the sandbox is NOT armed. */
|
|
210
|
+
unattested: Array<{ route: string; prefix: string; why: string }>;
|
|
118
211
|
}
|
|
119
212
|
|
|
120
213
|
/**
|
|
121
214
|
* Check a route table against the invariant. Pure — takes the route names so it
|
|
122
215
|
* can be unit-tested without booting a server, and so the caller decides what
|
|
123
216
|
* "reachable" means for its own dispatch shape.
|
|
217
|
+
*
|
|
218
|
+
* `sandboxArmed` is the A′1 contract, passed in rather than detected here: this
|
|
219
|
+
* module has no business importing the build host, and the caller is the only
|
|
220
|
+
* one who knows whether it wired it. Default `false` is deliberate — an unstated
|
|
221
|
+
* contract is an unmet one.
|
|
124
222
|
*/
|
|
125
223
|
export function checkContainment(
|
|
126
224
|
routeNames: Iterable<string>,
|
|
127
|
-
{
|
|
225
|
+
{
|
|
226
|
+
resolveModule,
|
|
227
|
+
sandboxArmed = false,
|
|
228
|
+
}: { resolveModule?: (specifier: string) => boolean; sandboxArmed?: boolean } = {}
|
|
128
229
|
): ContainmentReport {
|
|
129
230
|
const routes: ContainmentReport['routes'] = [];
|
|
231
|
+
const unattested: ContainmentReport['unattested'] = [];
|
|
130
232
|
for (const route of routeNames) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
233
|
+
const forbidden = FORBIDDEN_ROUTE_PREFIXES.find((f) => matches(route, f.prefix));
|
|
234
|
+
if (forbidden) {
|
|
235
|
+
routes.push({ route, prefix: forbidden.prefix, why: forbidden.why });
|
|
236
|
+
continue;
|
|
136
237
|
}
|
|
238
|
+
if (sandboxArmed) continue;
|
|
239
|
+
const sandboxed = SANDBOXED_ROUTE_PREFIXES.find((f) => matches(route, f.prefix));
|
|
240
|
+
if (sandboxed) unattested.push({ route, prefix: sandboxed.prefix, why: sandboxed.why });
|
|
137
241
|
}
|
|
138
242
|
|
|
139
243
|
const modules: string[] = [];
|
|
@@ -143,7 +247,12 @@ export function checkContainment(
|
|
|
143
247
|
}
|
|
144
248
|
}
|
|
145
249
|
|
|
146
|
-
return {
|
|
250
|
+
return {
|
|
251
|
+
ok: routes.length === 0 && modules.length === 0 && unattested.length === 0,
|
|
252
|
+
routes,
|
|
253
|
+
modules,
|
|
254
|
+
unattested,
|
|
255
|
+
};
|
|
147
256
|
}
|
|
148
257
|
|
|
149
258
|
/** Render a report as the message the operator sees when a cell refuses to boot. */
|
|
@@ -163,17 +272,36 @@ export function formatContainmentFailure(report: ContainmentReport): string {
|
|
|
163
272
|
}
|
|
164
273
|
lines.push('');
|
|
165
274
|
}
|
|
275
|
+
if (report.unattested.length > 0) {
|
|
276
|
+
lines.push(
|
|
277
|
+
'Canvas surfaces are reachable but the BUILD SANDBOX is not armed:',
|
|
278
|
+
...report.unattested.flatMap(({ route, prefix, why }) => [
|
|
279
|
+
` ${route}`,
|
|
280
|
+
` matches ${prefix} — ${why}`,
|
|
281
|
+
]),
|
|
282
|
+
'',
|
|
283
|
+
'These routes are permitted in a cell (DDR-209 A′1) — but only together',
|
|
284
|
+
'with the Phase 25 A1 contract: the canvas build runs in its OWN process,',
|
|
285
|
+
'with an EMPTY environment, an import allowlist and wall-clock + RSS',
|
|
286
|
+
'ceilings. Serving the shell without it means parsing tenant source in the',
|
|
287
|
+
'process that holds HUB_SECRET. Pass sandboxArmed once that host is wired.',
|
|
288
|
+
''
|
|
289
|
+
);
|
|
290
|
+
}
|
|
166
291
|
if (report.modules.length > 0) {
|
|
167
292
|
lines.push('Modules that resolve in this process and must not:');
|
|
168
293
|
for (const m of report.modules) lines.push(` ${m}`);
|
|
169
294
|
lines.push('');
|
|
170
295
|
}
|
|
171
296
|
lines.push(
|
|
172
|
-
'A cell
|
|
173
|
-
'
|
|
297
|
+
'A cell syncs, keeps history, stores assets and BUILDS a member’s own canvas',
|
|
298
|
+
'in a bounded sandbox. Evaluation happens in the member’s own browser, in a',
|
|
299
|
+
'segregated origin, where DDR-063/DDR-054 already contain it. Nothing here',
|
|
300
|
+
'renders, and no browser enters the image.',
|
|
174
301
|
'',
|
|
175
|
-
'If a feature genuinely needs one of
|
|
176
|
-
'non-executable synced unit) is its HARD PREREQUISITE — not a
|
|
302
|
+
'If a feature genuinely needs one of the FORBIDDEN surfaces, Direction B (a',
|
|
303
|
+
'structured, non-executable synced unit) is its HARD PREREQUISITE — not a',
|
|
304
|
+
'flag to add here.'
|
|
177
305
|
);
|
|
178
306
|
if (report.modules.length > 0) {
|
|
179
307
|
lines.push(
|
|
@@ -201,10 +329,15 @@ export function assertContainment(
|
|
|
201
329
|
{
|
|
202
330
|
env = process.env,
|
|
203
331
|
resolveModule,
|
|
204
|
-
|
|
332
|
+
sandboxArmed = false,
|
|
333
|
+
}: {
|
|
334
|
+
env?: NodeJS.ProcessEnv;
|
|
335
|
+
resolveModule?: (specifier: string) => boolean;
|
|
336
|
+
sandboxArmed?: boolean;
|
|
337
|
+
} = {}
|
|
205
338
|
): void {
|
|
206
339
|
if (!isWorkspaceMode(env)) return;
|
|
207
|
-
const report = checkContainment(routeNames, { resolveModule });
|
|
340
|
+
const report = checkContainment(routeNames, { resolveModule, sandboxArmed });
|
|
208
341
|
if (report.ok) return;
|
|
209
342
|
throw new Error(formatContainmentFailure(report));
|
|
210
343
|
}
|
package/apps/studio/ws.ts
CHANGED
|
@@ -21,6 +21,14 @@ export type WsData =
|
|
|
21
21
|
id: string;
|
|
22
22
|
remote: string;
|
|
23
23
|
kind: 'inspector';
|
|
24
|
+
/** Cloud Phase 27 — the role this socket was opened under, stamped at
|
|
25
|
+
* upgrade time from the proxy's injected header. `true` outside a cell
|
|
26
|
+
* only when the linked hub vouched `viewer`.
|
|
27
|
+
*
|
|
28
|
+
* It has to live on the SOCKET, not be re-read per message: a role is
|
|
29
|
+
* per session, and a handshake is the one moment the session is
|
|
30
|
+
* unambiguous. */
|
|
31
|
+
readOnly: boolean;
|
|
24
32
|
}
|
|
25
33
|
| {
|
|
26
34
|
id: string;
|
|
@@ -347,6 +355,28 @@ export function createWs(
|
|
|
347
355
|
}
|
|
348
356
|
if (!msg || typeof msg !== 'object') return;
|
|
349
357
|
try {
|
|
358
|
+
// Cloud Phase 27 — THE ROLE REACHES THE SOCKET TOO.
|
|
359
|
+
//
|
|
360
|
+
// The HTTP gate (http.ts `readOnlyRefusal`) does not see WebSocket
|
|
361
|
+
// frames, and comment creation is WS-driven — so without this a
|
|
362
|
+
// read-only session reached `comments-delete` and `comments-patch` over
|
|
363
|
+
// a socket while every equivalent HTTP write was refused. Found by
|
|
364
|
+
// reading what this channel actually accepts, after a live cell showed
|
|
365
|
+
// the HTTP `/_comments` route is GET-only.
|
|
366
|
+
//
|
|
367
|
+
// `comments-add` is deliberately NOT here: comment is the one write a
|
|
368
|
+
// viewer holds (role matrix, `viewer.comment === true`). Patch and
|
|
369
|
+
// delete are not — they change or remove somebody else's note.
|
|
370
|
+
const readOnlySocket = ws.data.kind === 'inspector' && ws.data.readOnly === true;
|
|
371
|
+
const MUTATES_OTHERS = new Set(['comments-patch', 'comments-delete']);
|
|
372
|
+
if (readOnlySocket && MUTATES_OTHERS.has(msg.type)) {
|
|
373
|
+
send(ws, {
|
|
374
|
+
type: 'refused',
|
|
375
|
+
reason: 'read-only',
|
|
376
|
+
message: 'Your role in this project is viewer — that change was not applied.',
|
|
377
|
+
});
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
350
380
|
if (msg.type === 'active' && typeof msg.file === 'string') inspect.setActive(msg.file);
|
|
351
381
|
else if (msg.type === 'tabs' && Array.isArray(msg.tabs)) inspect.setOpenTabs(msg.tabs);
|
|
352
382
|
else if (msg.type === 'select' && msg.selection) inspect.setSelected(msg.selection);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1agh/maude",
|
|
3
|
-
"version": "0.53.
|
|
3
|
+
"version": "0.53.2",
|
|
4
4
|
"description": "Marketplace of Claude Code plugins by Michal Dovrtěl: `design` (canvas-first design iteration) + `flow` (generic agentic workflow loop with .ai second brain). Ships the `maude` CLI (with `mdcc` legacy alias) to scaffold workspace, run the design dev server, and manage configs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"test:e2e:desktop:acp-cold-start": "pnpm --filter @maude/desktop-e2e e2e:acp-cold-start"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
|
-
"@1agh/maude-darwin-arm64": "0.53.
|
|
56
|
-
"@1agh/maude-darwin-x64": "0.53.
|
|
57
|
-
"@1agh/maude-linux-arm64": "0.53.
|
|
58
|
-
"@1agh/maude-linux-arm64-musl": "0.53.
|
|
59
|
-
"@1agh/maude-linux-x64": "0.53.
|
|
60
|
-
"@1agh/maude-linux-x64-musl": "0.53.
|
|
61
|
-
"@1agh/maude-win32-x64": "0.53.
|
|
55
|
+
"@1agh/maude-darwin-arm64": "0.53.2",
|
|
56
|
+
"@1agh/maude-darwin-x64": "0.53.2",
|
|
57
|
+
"@1agh/maude-linux-arm64": "0.53.2",
|
|
58
|
+
"@1agh/maude-linux-arm64-musl": "0.53.2",
|
|
59
|
+
"@1agh/maude-linux-x64": "0.53.2",
|
|
60
|
+
"@1agh/maude-linux-x64-musl": "0.53.2",
|
|
61
|
+
"@1agh/maude-win32-x64": "0.53.2"
|
|
62
62
|
},
|
|
63
63
|
"files": [
|
|
64
64
|
"cli",
|