@1agh/maude 0.54.0 → 0.55.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/apps/studio/annotations-layer.tsx +11 -1
- package/apps/studio/canvas-build-sandbox.ts +101 -9
- package/apps/studio/canvas-build-worker.ts +7 -1
- package/apps/studio/canvas-build.ts +9 -1
- package/apps/studio/client/app.jsx +18 -0
- package/apps/studio/client/github.js +7 -0
- package/apps/studio/client/panels/CloudBar.jsx +461 -40
- package/apps/studio/client/styles/3-shell-maude.css +30 -0
- package/apps/studio/cloud/endpoints.ts +48 -6
- package/apps/studio/dist/client.bundle.js +581 -581
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/http.ts +14 -1
- package/apps/studio/test/cloud-endpoints.test.ts +231 -4
- package/apps/studio/whats-new.json +18 -0
- package/package.json +8 -8
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
19
19
|
import { homedir } from 'node:os';
|
|
20
|
-
import { dirname, join } from 'node:path';
|
|
20
|
+
import { basename, dirname, join } from 'node:path';
|
|
21
21
|
|
|
22
22
|
import { saveHubCredential } from '../sync/hub-link.ts';
|
|
23
|
-
import { normalizeUrl } from '../sync/hubs-config.ts';
|
|
23
|
+
import { getHubToken, normalizeUrl } from '../sync/hubs-config.ts';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Where Maude Cloud lives, resolved PER CALL rather than at module load.
|
|
@@ -113,14 +113,28 @@ interface Ctx {
|
|
|
113
113
|
|
|
114
114
|
export function createCloudEndpoints(ctx: Ctx) {
|
|
115
115
|
return {
|
|
116
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* Signed in? Who? And WHICH folder is asking? Cheap — reads two files,
|
|
118
|
+
* never the network.
|
|
119
|
+
*
|
|
120
|
+
* `project` + `linkedHub` are the local half of the answer, and they exist
|
|
121
|
+
* for one reason: a maude:// link names a CLOUD project, and the person
|
|
122
|
+
* confirming it deserves to see which LOCAL folder is about to be attached
|
|
123
|
+
* to it. Both are already-public facts (a directory name, and the
|
|
124
|
+
* token-free `linkedHub` this same module writes into a committed
|
|
125
|
+
* config.json) — no credential material widens by being reported here.
|
|
126
|
+
*/
|
|
117
127
|
status(): CloudEndpointResult {
|
|
118
128
|
const file = readCloudFile();
|
|
119
129
|
return {
|
|
120
130
|
status: 200,
|
|
121
|
-
json:
|
|
122
|
-
|
|
123
|
-
:
|
|
131
|
+
json: {
|
|
132
|
+
connected: !!file,
|
|
133
|
+
email: file?.email ?? null,
|
|
134
|
+
url: file ? file.url : cloudUrl(),
|
|
135
|
+
project: basename(ctx.paths.repoRoot),
|
|
136
|
+
linkedHub: readLinkedHub(),
|
|
137
|
+
},
|
|
124
138
|
};
|
|
125
139
|
},
|
|
126
140
|
|
|
@@ -292,6 +306,34 @@ export function createCloudEndpoints(ctx: Ctx) {
|
|
|
292
306
|
},
|
|
293
307
|
};
|
|
294
308
|
|
|
309
|
+
/**
|
|
310
|
+
* The workspace this folder already answers to, if any. Address only.
|
|
311
|
+
*
|
|
312
|
+
* `credentialed` is the half that can be trusted. `config.json` is COMMITTED
|
|
313
|
+
* and travels with the repo, so a `linkedHub` in it is attacker-authorable:
|
|
314
|
+
* publish a template pointing at your own cell and the connect dialog would
|
|
315
|
+
* cheerfully print "this folder is already linked to <you>" — the strongest
|
|
316
|
+
* reassurance it can give, produced entirely by content the person merely
|
|
317
|
+
* opened (attacker pass 2026-08-04, B2). A stored hub credential for that
|
|
318
|
+
* address is the corroboration, because only a real sign-in writes one.
|
|
319
|
+
*/
|
|
320
|
+
function readLinkedHub(): { url: string; credentialed: boolean } | null {
|
|
321
|
+
try {
|
|
322
|
+
const cfg = JSON.parse(readFileSync(join(ctx.paths.designRoot, 'config.json'), 'utf8'));
|
|
323
|
+
const url = cfg?.linkedHub?.url;
|
|
324
|
+
if (typeof url !== 'string' || !url) return null;
|
|
325
|
+
let credentialed = false;
|
|
326
|
+
try {
|
|
327
|
+
credentialed = !!getHubToken(normalizeUrl(url));
|
|
328
|
+
} catch {
|
|
329
|
+
/* unreadable credential store → treat as uncorroborated */
|
|
330
|
+
}
|
|
331
|
+
return { url, credentialed };
|
|
332
|
+
} catch {
|
|
333
|
+
return null; // absent/malformed → simply not linked
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
295
337
|
/** The shared tail of every attach: cell exchange → credential + linkedHub. */
|
|
296
338
|
async function linkToWorkspace({
|
|
297
339
|
workspaceUrl,
|