makersclaw 0.5.2 → 0.6.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.
Files changed (73) hide show
  1. package/README.md +29 -3
  2. package/package.json +3 -2
  3. package/r/annotate.json +3 -3
  4. package/r/approval-request.json +2 -2
  5. package/r/audio-player.json +2 -2
  6. package/r/auth-form.json +2 -2
  7. package/r/board.json +2 -2
  8. package/r/calendar-view.json +3 -3
  9. package/r/cart.json +2 -2
  10. package/r/chart.json +2 -2
  11. package/r/chat.json +2 -2
  12. package/r/code-editor.json +2 -2
  13. package/r/comment-box.json +3 -3
  14. package/r/contact-section.json +2 -2
  15. package/r/csv-import.json +3 -3
  16. package/r/data-table.json +2 -2
  17. package/r/diagram.json +2 -2
  18. package/r/doc-editor.json +2 -2
  19. package/r/doc-page.json +3 -3
  20. package/r/email-render.json +2 -2
  21. package/r/faq.json +2 -2
  22. package/r/file-upload.json +2 -2
  23. package/r/flow-canvas.json +2 -2
  24. package/r/footer.json +2 -2
  25. package/r/gantt.json +3 -3
  26. package/r/job-panel.json +2 -2
  27. package/r/json-editor.json +3 -3
  28. package/r/map.json +2 -2
  29. package/r/menubar.json +2 -2
  30. package/r/mind-map.json +3 -3
  31. package/r/navigation-menu.json +2 -2
  32. package/r/order-detail.json +2 -2
  33. package/r/org-chart.json +3 -3
  34. package/r/page-builder.json +2 -2
  35. package/r/payment-methods.json +2 -2
  36. package/r/pdf-document.json +2 -2
  37. package/r/pdf-viewer.json +2 -2
  38. package/r/product-detail.json +2 -2
  39. package/r/product-grid.json +3 -3
  40. package/r/record-form.json +2 -2
  41. package/r/record-notes.json +4 -4
  42. package/r/registry.json +121 -121
  43. package/r/search-dialog.json +2 -2
  44. package/r/settings-list.json +2 -2
  45. package/r/setup-checklist.json +2 -2
  46. package/r/share-dialog.json +2 -2
  47. package/r/sidebar.json +2 -2
  48. package/r/signature-pad.json +2 -2
  49. package/r/sketch-canvas.json +2 -2
  50. package/r/spreadsheet.json +2 -2
  51. package/r/stat-cards.json +3 -3
  52. package/r/task-list.json +3 -3
  53. package/r/task-model.json +2 -2
  54. package/r/testimonials.json +2 -2
  55. package/r/transaction-list.json +2 -2
  56. package/r/whiteboard.json +3 -3
  57. package/src/cli.mjs +35 -6
  58. package/src/install.mjs +101 -4
  59. package/src/lockfile.mjs +468 -0
  60. package/src/pm.mjs +473 -0
  61. package/src/registry.mjs +48 -1
  62. package/templates/next/files/README.md +20 -15
  63. package/templates/next/files/app/claw-alive/route.js +2 -2
  64. package/templates/next/files/app/frame.js +6 -5
  65. package/templates/next/files/app/layout.jsx +2 -2
  66. package/templates/next/files/check/run.mjs +55 -14
  67. package/templates/next/files/lib/actions.js +1 -1
  68. package/templates/next/files/lib/data.js +1 -1
  69. package/templates/next/files/next.config.mjs +50 -8
  70. package/templates/next/files/package.json +3 -3
  71. package/templates/next/files/{middleware.js → proxy.js} +13 -6
  72. package/templates/next/pnpm-lock.yaml +5870 -0
  73. package/templates/next/template.json +5 -4
@@ -17,23 +17,37 @@
17
17
  // npm run check -- --static static rules only
18
18
  //
19
19
  // The smoke test builds for itself, and only when a source file is newer
20
- // than its last build. Where: in the sandbox the app folder is
21
- // `ubuntu:claw 2755` — the terminal user can read it, not write in it —
22
- // so the sources are copied to a folder of its own (`~/.claw-check/<app>`,
23
- // node_modules symlinked back) and built there. On a writable checkout
24
- // (local dev) it builds in place, into `.next-check` (CLAW_DIST_DIR,
25
- // next.config.mjs). Never into `.next`: that is the dev server's, and a
26
- // second build there dies with EACCES on .next/trace. The founder's live
27
- // preview keeps running, untouched, while the check runs beside it.
20
+ // than its last build. Where: in place when the app folder is writable,
21
+ // into `.next-check` (CLAW_DIST_DIR, next.config.mjs). Where it is not (a
22
+ // sandbox tree made `2755` before claw opened app trees to its `claw`
23
+ // group, tree-access.ts), the sources are copied to a folder of its own
24
+ // (`~/.claw-check/<app>`, node_modules symlinked back) and built there.
25
+ //
26
+ // Never into `.next`: it is not the check's. In a working copy it is the
27
+ // preview dev server's; in a live app it holds the production build the
28
+ // platform made and serves, and whose .next/BUILD_ID it reads as proof of
29
+ // a build. The founder's live preview keeps running, untouched, while the
30
+ // check runs beside it. What Next 16 changed (16.3.7, 2026-09-29): `next
31
+ // dev` keeps its own files in `.next/dev`, and a build by the same user
32
+ // beside a running dev server works and leaves `dev/` alone. Under claw's
33
+ // umask 002 a `.next` the dev server makes is 775, so the EACCES on
34
+ // .next/trace that Next 15 hit across users should not happen in today's
35
+ // sandbox (not tried with two Linux users). It comes back wherever the
36
+ // builder cannot write `.next` (`chmod 555` on it: EACCES on .next/trace),
37
+ // which is where one Linux user per app, claw's planned walls, leads.
38
+ //
39
+ // A copy's node_modules is a symlink back to the app's, and Turbopack
40
+ // reads nothing outside its root, so the copy's build is told a root
41
+ // that holds both (CLAW_TURBOPACK_ROOT, commonRoot below).
28
42
  //
29
43
  // Output is meant to be read by the platform agent in one glance: keep
30
44
  // it under twenty lines, name file:line, say what to do instead.
31
45
 
32
- import { accessSync, constants, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, symlinkSync } from "node:fs";
46
+ import { accessSync, constants, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, symlinkSync } from "node:fs";
33
47
  import { createHash } from "node:crypto";
34
48
  import { spawn, spawnSync } from "node:child_process";
35
49
  import { createServer } from "node:net";
36
- import { basename, dirname, join, relative } from "node:path";
50
+ import { basename, dirname, join, relative, sep } from "node:path";
37
51
  import { homedir, tmpdir } from "node:os";
38
52
  import { fileURLToPath } from "node:url";
39
53
 
@@ -47,8 +61,11 @@ const STATIC_ONLY = process.argv.includes("--static");
47
61
  // `kit` rule refuses it (a shared piece goes in components/, a picture in
48
62
  // components/depictions/). The list is the template's; `makersclaw
49
63
  // update` lays both folders again.
50
- // Exact names AND extensions: Next resolves .js before .jsx, so a
51
- // components/ui/depiction.js beside depiction.jsx would win unseen.
64
+ // Exact names AND extensions: a file of the same name with an extension
65
+ // the bundler tries first wins unseen. Next 15's webpack tried .js before
66
+ // .jsx (a components/ui/depiction.js beside depiction.jsx won); Next 16's
67
+ // Turbopack tries .jsx before .js (seen on 16.3.7), so the kit's own file
68
+ // wins there, but the rule holds for every bundler.
52
69
  const KIT = /^components\/(?:ui\/(?:cx|index)\.js|ui\/(?:radio|toggle|button-group|avatar|breadcrumb|pagination|button|collapsible|item|table|depiction|feedback|stat|distribution|swatch|steps|separator|scroll-area|field|icon|menu|context-menu|popover|calendar|date-picker|tooltip|notice|sheet|tabs|slider|input-group|image|file-input|input-otp|command|combobox|rating|toast|carousel|resizable)\.jsx|parts\/(?:index|sample)\.js|parts\/(?:fixture|record-switcher|live-work)\.jsx)$/;
53
70
 
54
71
  // The pins: sha256 of every fixed file, written by `makersclaw init` and
@@ -104,7 +121,7 @@ const SKIP = [
104
121
  /^app\/frame\.js$/,
105
122
  /^app\/claw-alive\/route\.js$/,
106
123
  /^app\/s\/\[key\]\/page\.jsx$/,
107
- /^middleware\.js$/,
124
+ /^proxy\.js$/,
108
125
  /^next\.config\.mjs$/,
109
126
  /^postcss\.config\.mjs$/,
110
127
  /^public\//,
@@ -344,6 +361,13 @@ const surfaceKeys = [];
344
361
  if (e.isFile() && /^(?:ui|parts|depictions|blocks)\.[^.]+$/.test(e.name)) L.hit(`components/${e.name}`, "shadow", `a file beside the components/${e.name.replace(/\..*$/, "")}/ folder wins module resolution over it; delete it`);
345
362
  }
346
363
  }
364
+ // Next 16 runs proxy.js (fixed) before every request. A middleware file
365
+ // beside it, the name Next 15 used, fails the build; alone it would run
366
+ // in the token check's place. `makersclaw update` removes the template's
367
+ // own from 0.5.x.
368
+ for (const e of existsSync(ROOT) ? readdirSync(ROOT) : []) {
369
+ if (/^(?:middleware|proxy)\.(?:js|jsx|mjs|cjs|ts|tsx|mts|cts)$/.test(e) && e !== "proxy.js") L.hit(e, "proxy", `Next 16 runs proxy.js, the template's fixed token check; delete ${e}`);
370
+ }
347
371
  // check/ is this script and its pins; a module hidden there is bundled
348
372
  // by Next and read by no rule.
349
373
  if (existsSync(join(ROOT, "check"))) {
@@ -656,6 +680,18 @@ function buildSite() {
656
680
  return { dir: join(home, ".claw-check", name), dist: ".next", copied: true };
657
681
  }
658
682
 
683
+ /** The nearest folder holding both paths, by their real paths ("/" at
684
+ * worst). A copy's build reads node_modules through a symlink back to the
685
+ * app, and Turbopack reads nothing outside its root: the check hands it
686
+ * this folder as the root (CLAW_TURBOPACK_ROOT, next.config.mjs). */
687
+ function commonRoot(a, b) {
688
+ const x = realpathSync(a).split(sep);
689
+ const y = realpathSync(b).split(sep);
690
+ let i = 0;
691
+ while (i < x.length && i < y.length && x[i] === y[i]) i++;
692
+ return x.slice(0, i).join(sep) || sep;
693
+ }
694
+
659
695
  /** Copy the app's sources (never node_modules or a build) to `dir`, and
660
696
  * point its node_modules back at the app's. */
661
697
  function copySources(dir) {
@@ -693,7 +729,12 @@ function buildForCheck(site, env) {
693
729
  async function smoke() {
694
730
  const site = buildSite();
695
731
  const base = { ...process.env, ...dotenv(join(ROOT, ".env")), NODE_ENV: "production", HOSTNAME: "127.0.0.1", CLAW_DIST_DIR: site.dist };
696
- delete base.CLAW_PRODUCT_TOKEN; // the check is not the proxy; the middleware would 401 it
732
+ delete base.CLAW_TURBOPACK_ROOT;
733
+ if (site.copied) {
734
+ mkdirSync(site.dir, { recursive: true });
735
+ base.CLAW_TURBOPACK_ROOT = commonRoot(site.dir, ROOT);
736
+ }
737
+ delete base.CLAW_PRODUCT_TOKEN; // the check is not the product proxy; proxy.js would 401 it
697
738
  const built = buildForCheck(site, base);
698
739
  if (!built.ok) {
699
740
  fail("smoke", "build", `next build failed:\n${built.tail}`);
@@ -10,7 +10,7 @@ import { ident, logActivity, query } from "./db";
10
10
  // are quoted through ident(), which refuses anything that is not a plain
11
11
  // identifier. Returns { ok } or { ok: false, error }; never throws.
12
12
  //
13
- // `surface` is optional: middleware.js stamps the current surface key on
13
+ // `surface` is optional: proxy.js stamps the current surface key on
14
14
  // the request, so a surface rarely needs to pass it.
15
15
  //
16
16
  // `detail` is the founder's sentence for the row. The OS Activity tab
@@ -160,7 +160,7 @@ export async function loadActivity({ limit = 100, surface, since } = {}) {
160
160
  * code keeps one import. */
161
161
  export { markSample };
162
162
 
163
- /** The surface key of the current request (middleware.js sets it from
163
+ /** The surface key of the current request (proxy.js sets it from
164
164
  * /s/<key>), unless the caller names one — a string, or the page's
165
165
  * `surface` object. */
166
166
  export async function currentSurface(explicit) {
@@ -7,8 +7,8 @@
7
7
  // attribute app/layout.jsx renders is the runtime copy and is read first, so
8
8
  // a start under a different prefix than the build still resolves.
9
9
  //
10
- // allowedOrigins is NOT optional here, and it is not yours to edit. Next 15
11
- // refuses a Server Action whose `Origin` header disagrees with
10
+ // allowedOrigins is NOT optional here, and it is not yours to edit. Next
11
+ // (15 and 16) refuses a Server Action whose `Origin` header disagrees with
12
12
  // `x-forwarded-host` — and in this stack they always disagree, because the
13
13
  // sandbox ingress rewrites `x-forwarded-host` to its own vercel.run name
14
14
  // while the browser is on the product host. Without this the app loads
@@ -23,19 +23,61 @@ const allowedOrigins = (process.env.CLAW_ALLOWED_ORIGINS || "")
23
23
  .map((o) => o.trim())
24
24
  .filter(Boolean);
25
25
 
26
+ // The same hosts, for `next dev` alone. Next 16 refuses a request for a
27
+ // dev resource (/_next/*, /__nextjs*: the HMR socket, the error overlay's
28
+ // lookups) whose Origin host is not localhost or listed here; Next 15 only
29
+ // warned. The preview's browser is on the product host, so without this
30
+ // every such request answers 403. Hostnames only: Next compares no port.
31
+ const allowedDevOrigins = [
32
+ ...new Set(
33
+ allowedOrigins
34
+ .map((o) => o.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "").replace(/\/.*$/, "").replace(/:\d+$/, "").toLowerCase())
35
+ .filter(Boolean),
36
+ ),
37
+ ];
38
+
26
39
  // `npm run check` builds into its own folder (CLAW_DIST_DIR=.next-check,
27
- // check/run.mjs) so it never touches `.next`: in the sandbox the running
28
- // dev server owns that folder as another user, and a second `next build`
29
- // there dies with EACCES on .next/trace before it starts.
40
+ // check/run.mjs) so it never touches `.next`, which is not the check's:
41
+ // in a working copy it is the dev server's, and in a live app it holds
42
+ // the production build the platform made, serves and reads as its proof
43
+ // (.next/BUILD_ID). check/run.mjs says more.
44
+ //
45
+ // CLAW_TURBOPACK_ROOT is set by `npm run check` alone, when it builds a
46
+ // copy of an app folder it cannot write (check/run.mjs buildSite). The
47
+ // copy's node_modules is a symlink back to the app's, and Turbopack (Next
48
+ // 16's bundler for build as well as dev) refuses a symlink that leaves its
49
+ // root: "Symlink [project]/node_modules is invalid, it points out of the
50
+ // filesystem root". The check names the nearest folder holding both.
51
+ // Unset, Turbopack finds the root itself.
52
+ const turbopackRoot = process.env.CLAW_TURBOPACK_ROOT || "";
53
+
54
+ // agentRules: false. Next 16's `next dev` writes AGENTS.md and CLAUDE.md
55
+ // into the app folder when it sees an AI agent in its environment
56
+ // (AI_AGENT, CLAUDECODE…), telling the agent to read Next's own docs.
57
+ // This app's agent brief is the platform's, beside the app, and the app
58
+ // folder holds only what the template and the app's own screens put there.
59
+ //
60
+ // mcpServer: false. Next 16's `next dev` also serves an MCP endpoint at
61
+ // /_next/mcp (the app's routes, logs and errors, the errors of every
62
+ // browser on the page, a route compile) and answers it before proxy.js
63
+ // runs, so no product token guards it. Off: the token check is meant to
64
+ // be the preview's only door. One more answers there that no setting
65
+ // turns off, the dev overlay's /__nextjs_attach-nodejs-inspector (it
66
+ // opens a Node debugger on loopback); only the platform can wall that
67
+ // (CHANGELOG, 0.6.0).
30
68
  const nextConfig = {
31
69
  basePath: process.env.CLAW_BASE_PATH || "",
32
70
  distDir: process.env.CLAW_DIST_DIR || ".next",
33
71
  env: {
34
72
  CLAW_BASE_PATH: process.env.CLAW_BASE_PATH || "",
35
73
  },
36
- ...(allowedOrigins.length > 0
37
- ? { experimental: { serverActions: { allowedOrigins } } }
38
- : {}),
74
+ agentRules: false,
75
+ ...(allowedDevOrigins.length > 0 ? { allowedDevOrigins } : {}),
76
+ ...(turbopackRoot ? { turbopack: { root: turbopackRoot }, outputFileTracingRoot: turbopackRoot } : {}),
77
+ experimental: {
78
+ mcpServer: false,
79
+ ...(allowedOrigins.length > 0 ? { serverActions: { allowedOrigins } } : {}),
80
+ },
39
81
  };
40
82
 
41
83
  export default nextConfig;
@@ -10,10 +10,10 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@tailwindcss/postcss": "^4",
13
- "next": "^15.4.0",
13
+ "next": "^16.3.7",
14
14
  "pg": "^8.16.0",
15
- "react": "^19.1.0",
16
- "react-dom": "^19.1.0",
15
+ "react": "^19.3.0",
16
+ "react-dom": "^19.3.0",
17
17
  "tailwindcss": "^4"
18
18
  }
19
19
  }
@@ -1,8 +1,15 @@
1
1
  import { NextResponse } from "next/server";
2
2
 
3
- // The only door is the Makersclaw dashboard proxy, which stamps this token
4
- // on every request. The sandbox port itself is public, so without this
5
- // check anyone with the URL could read the founder's data.
3
+ // Next runs this before every request. Until 0.6.0 it was middleware.js
4
+ // (Next 15's name for it); Next 16 renamed the file and its export to
5
+ // `proxy`, and runs it on Node, never the edge runtime. A middleware.js
6
+ // beside this file fails the build, so `makersclaw update` removes the old
7
+ // one. Not to be confused with the product proxy, the Makersclaw dashboard
8
+ // door that sits in front of the whole app.
9
+ //
10
+ // The only door is that product proxy, which stamps this token on every
11
+ // request. The sandbox port itself is public, so without this check
12
+ // anyone with the URL could read the founder's data.
6
13
  //
7
14
  // It also tells the server which surface a request is for: /s/<key> becomes
8
15
  // the x-claw-surface request header, so lib/data.js and lib/actions.js can
@@ -13,12 +20,12 @@ import { NextResponse } from "next/server";
13
20
  // the desk, and the product proxy carries it as the x-claw-theme header
14
21
  // on every later request (the browser's cookies never reach the app).
15
22
  // ?theme= on any URL wins for that request and sets the claw_theme cookie
16
- // too, so the app keeps its theme when run without the proxy (local
17
- // `next dev`). app/layout.jsx reads header, then cookie, onto
23
+ // too, so the app keeps its theme when run without the product proxy
24
+ // (local `next dev`). app/layout.jsx reads header, then cookie, onto
18
25
  // <html data-theme>.
19
26
  const THEMES = new Set(["light", "dark"]);
20
27
 
21
- export function middleware(request) {
28
+ export function proxy(request) {
22
29
  const expected = process.env.CLAW_PRODUCT_TOKEN;
23
30
  if (expected && request.headers.get("x-claw-product-token") !== expected) {
24
31
  return new NextResponse("Open this app from your Makersclaw dashboard.", {