forgecad 0.9.14 → 0.9.15
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/LICENSE +6 -4
- package/README.md +8 -4
- package/dist/assets/{AdminPage-eWGs2K6H.js → AdminPage-CDyGUinA.js} +2 -2
- package/dist/assets/{BenchmarkPage-CTrLKfpo.js → BenchmarkPage-DfPMY_-d.js} +4 -15
- package/dist/assets/{BlogPage-5nPesyds.js → BlogPage-kF0fkdJT.js} +2 -2
- package/dist/assets/{DocsPage-C4Y3nbYc.js → DocsPage-B954L3YN.js} +9 -3
- package/dist/assets/EditorApp-Beb-IZ0y.js +14014 -0
- package/dist/assets/{EditorApp-BAnckbsk.css → EditorApp-CuDLxKqL.css} +698 -0
- package/dist/assets/{EmbedViewer-C8fB4n5U.js → EmbedViewer-C77B-TrF.js} +3 -3
- package/dist/assets/{LandingPageProofDriven-jSz0LaMM.js → LandingPageProofDriven-Cr6fXMDj.js} +35 -37
- package/dist/assets/LegalPage-BRlScr9A.css +91 -0
- package/dist/assets/LegalPage-Dzklqmmg.js +39 -0
- package/dist/assets/{PricingPage-BMedqFef.css → PricingPage-BPF6HKyO.css} +25 -0
- package/dist/assets/{PricingPage-B83B90zh.js → PricingPage-zWXkvlwl.js} +19 -19
- package/dist/assets/{SettingsPage-DY889pcu.js → SettingsPage-Bz0of4KQ.js} +2 -2
- package/dist/assets/app-CE3sYcV7.css +3890 -0
- package/dist/assets/{app-bEww1ic4.js → app-D3kDkggg.js} +2293 -946
- package/dist/assets/cli/{render-Cho2uKG_.js → render-DSY3mMQa.js} +337 -7
- package/dist/assets/{constructionHistoryWorker-HYwzJY4m.js → constructionHistoryWorker-gpDo-uH2.js} +927 -243
- package/dist/assets/{evalWorker-CjQwJSE-.js → evalWorker-CU0Ke6DP.js} +7800 -4164
- package/dist/assets/{forgecad_geometry-CH2nvuLA.js → forgecad_geometry-Dgceylq9.js} +43 -1
- package/dist/assets/forgecad_geometry_bg-dD4RNQF1.wasm +0 -0
- package/dist/assets/{inspectWorker-DeRnMVv1.js → inspectWorker-COyp8XXA.js} +927 -243
- package/dist/assets/{javascript-70-4uGcz.js → javascript-1kQXfVaz.js} +1 -1
- package/dist/assets/landing-proof-driven-DiGqdtWa.js +18 -0
- package/dist/assets/{landing-proof-driven-oFYW6mjz.css → landing-proof-driven-ORyigZ6p.css} +13 -7
- package/dist/assets/legalContent-ZfFGMmi4.js +251 -0
- package/dist/assets/{manifold-CG9Fokx-.js → manifold-BRI5prcH.js} +1 -1
- package/dist/assets/{manifold-uRzgk5O8.js → manifold-C-3h2M7p.js} +2 -2
- package/dist/assets/{manifold-rmfAcdwF.js → manifold-DNkrUWpA.js} +1 -1
- package/dist/assets/{reportWorker-4cW_ZpoS.js → reportWorker-CdBz5bNg.js} +7538 -10857
- package/dist/assets/{scalar-sampling-budget-CfDiFvh7.js → scalar-sampling-budget-wJF98aY9.js} +6935 -4331
- package/dist/assets/{scanProxyWorker-Bs2TDgLw.js → scanProxyWorker-B-9VbLIs.js} +32 -1
- package/dist/assets/{solver-DuJAO8S6.js → solver-BZ9LPTHs.js} +1 -1
- package/dist/assets/solver_bg-DAHZJ_rw.wasm +0 -0
- package/dist/assets/{targets-D6PWsv6X.js → targets-B9sGB5nB.js} +1 -1
- package/dist/assets/{vendor-react-Da3A2QmU.js → vendor-react-6j1Kke-Y.js} +6 -5
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/AI/ai-native-cad.md +50 -0
- package/dist/docs-raw/AI/usage.md +3 -12
- package/dist/docs-raw/CLI.md +30 -10
- package/dist/docs-raw/component-model.md +27 -11
- package/dist/docs-raw/generated/assembly.md +301 -212
- package/dist/docs-raw/generated/concepts.md +235 -237
- package/dist/docs-raw/generated/core.md +283 -6
- package/dist/docs-raw/generated/curves.md +274 -361
- package/dist/docs-raw/generated/lib.md +7 -1
- package/dist/docs-raw/generated/output.md +19 -4
- package/dist/docs-raw/generated/runtime-names.md +41 -0
- package/dist/docs-raw/generated/sdf.md +31 -0
- package/dist/docs-raw/generated/sheet-metal.md +9 -0
- package/dist/docs-raw/generated/sketch.md +44 -1
- package/dist/docs-raw/generated/viewport.md +11 -3
- package/dist/docs-raw/guides/coordinate-system.md +20 -16
- package/dist/docs-raw/guides/geometry-conventions.md +2 -2
- package/dist/docs-raw/guides/inspection-bundles.md +2 -1
- package/dist/docs-raw/guides/joint-design.md +24 -0
- package/dist/docs-raw/guides/positioning.md +13 -3
- package/dist/docs-raw/legal/privacy.md +63 -0
- package/dist/docs-raw/legal/software-license.md +55 -0
- package/dist/docs-raw/legal/terms.md +87 -0
- package/dist/docs-raw/skills/forgecad-3d-reconstruction.md +1 -1
- package/dist/docs-raw/skills/forgecad-blockout-model.md +1 -1
- package/dist/docs-raw/skills/forgecad-component-model.md +11 -2
- package/dist/docs-raw/skills/forgecad-high-level-spec.md +1 -1
- package/dist/docs-raw/skills/forgecad-image-replicator.md +8 -8
- package/dist/docs-raw/skills/forgecad-lld.md +1 -1
- package/dist/docs-raw/skills/forgecad-make-a-model.md +1 -1
- package/dist/docs-raw/skills/forgecad-model-grader.md +2 -2
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +2 -2
- package/dist/docs-raw/skills/forgecad-project.md +1 -1
- package/dist/docs-raw/skills/forgecad-reconstruction-benchmark.md +1 -1
- package/dist/docs-raw/skills/forgecad-render-inspect.md +4 -2
- package/dist/docs-raw/skills/forgecad-visual-spec.md +1 -1
- package/dist/docs-raw/skills/forgecad.md +4 -3
- package/dist/index.html +40 -12
- package/dist/llms.txt +8 -0
- package/dist/site.webmanifest +1 -1
- package/dist/sitemap.xml +49 -13
- package/dist-cli/{check-compiler-U5SOPN7X.js → check-compiler-SDX5QIXI.js} +1 -2
- package/dist-cli/{check-query-propagation-XOKNSSYU.js → check-query-propagation-EAYEFT77.js} +1 -2
- package/dist-cli/{chunk-EXWGNL6K.js → chunk-N4O47JLF.js} +12540 -9046
- package/dist-cli/forgecad.js +1786 -679
- package/dist-cli/{forgecad_geometry-GYVNKPIE.js → forgecad_geometry-QOQIIP53.js} +42 -1
- package/dist-cli/forgecad_geometry_bg.wasm +0 -0
- package/dist-cli/{solver-46FFSK2U.js → solver-OK4HECRH.js} +0 -1
- package/dist-cli/solver_bg.wasm +0 -0
- package/dist-skill/CONTEXT.md +1117 -721
- package/dist-skill/SKILL.md +3 -2
- package/dist-skill/docs/API/core/concepts.md +64 -1
- package/dist-skill/docs/CLI.md +30 -10
- package/dist-skill/docs/generated/assembly.md +277 -229
- package/dist-skill/docs/generated/core.md +283 -6
- package/dist-skill/docs/generated/curves.md +272 -362
- package/dist-skill/docs/generated/lib.md +7 -1
- package/dist-skill/docs/generated/output.md +19 -4
- package/dist-skill/docs/generated/runtime-names.md +41 -0
- package/dist-skill/docs/generated/sdf.md +31 -0
- package/dist-skill/docs/generated/sheet-metal.md +9 -0
- package/dist-skill/docs/generated/sketch.md +44 -2
- package/dist-skill/docs/generated/viewport.md +2 -87
- package/dist-skill/docs/guides/coordinate-system.md +20 -16
- package/dist-skill/docs/guides/geometry-conventions.md +2 -2
- package/dist-skill/docs/guides/inspection-bundles.md +2 -1
- package/dist-skill/docs/guides/joint-design.md +24 -0
- package/dist-skill/docs/guides/positioning.md +13 -3
- package/dist-skill/library/forgecad-component-model/SKILL.md +10 -1
- package/dist-skill/library/forgecad-image-replicator/SKILL.md +6 -6
- package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.py +166 -0
- package/dist-skill/library/forgecad-model-grader/SKILL.md +1 -1
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +3 -1
- package/examples/api/assembly-kinematics-foundation.forge.js +65 -0
- package/examples/api/assembly-kinematics-four-bar.forge.js +115 -0
- package/examples/api/assembly-kinematics-limb.forge.js +116 -0
- package/examples/api/connector-frame-rig-chain.forge.js +102 -0
- package/examples/api/exact-sheet-shell-assembly.forge.js +0 -2
- package/examples/api/exact-surface-studio.forge.js +6 -8
- package/examples/api/helix-basics.forge.js +6 -6
- package/examples/api/lean-foundations/README.md +12 -0
- package/examples/api/lean-foundations/curve-blend-exact.forge.js +22 -0
- package/examples/api/lean-foundations/curve-fit-interpolation.forge.js +18 -0
- package/examples/api/lean-foundations/curve-helix-canonicalization.forge.js +27 -0
- package/examples/api/lean-foundations/curve-route-canonicalization.forge.js +16 -0
- package/examples/api/lean-foundations/curve-trim-reverse.forge.js +24 -0
- package/examples/api/lean-foundations/exact-curve-arc.forge.js +36 -0
- package/examples/api/mixed-edge-finishes-proof.forge.js +8 -11
- package/examples/api/route3d-elbow.forge.js +68 -0
- package/examples/api/transition-curves.forge.js +44 -15
- package/examples/api/y-blend-corner-showcase.forge.js +0 -2
- package/examples/generative/coral-vase.forge.js +1 -1
- package/examples/nurbs-tube.forge.js +1 -1
- package/package.json +14 -13
- package/dist/assets/EditorApp-lXv53A1m.js +0 -13610
- package/dist/assets/app-CsHnaBWt.css +0 -1789
- package/dist/assets/forgecad_geometry_bg-C5_E9Oa9.wasm +0 -0
- package/dist/assets/solver_bg-CWvv4lnN.wasm +0 -0
- package/dist/docs-raw/API/README.md +0 -16
- package/dist/docs-raw/API/core/concepts.md +0 -118
- package/dist/docs-raw/INDEX.md +0 -138
- package/dist/docs-raw/RELEASING.md +0 -87
- package/dist/docs-raw/agent-native-api.md +0 -27
- package/dist/docs-raw/beta-deployment.md +0 -304
- package/dist/docs-raw/beta-operations.md +0 -325
- package/dist/docs-raw/blueprint-first.md +0 -145
- package/dist/docs-raw/cli-monetization.md +0 -112
- package/dist/docs-raw/coding-best-practices.md +0 -120
- package/dist/docs-raw/coding.md +0 -340
- package/dist/docs-raw/deployment.md +0 -374
- package/dist/docs-raw/guides/skill-maintenance.md +0 -161
- package/dist/docs-raw/guides/surface-members.md +0 -82
- package/dist/docs-raw/harbor-cli.md +0 -854
- package/dist/docs-raw/internals/backend-vocabulary.md +0 -35
- package/dist/docs-raw/internals/compiler.md +0 -307
- package/dist/docs-raw/internals/constraint-solver-quality.md +0 -161
- package/dist/docs-raw/internals/constraint-solver.md +0 -176
- package/dist/docs-raw/internals/shape-from-slices.md +0 -152
- package/dist/docs-raw/internals/sketch-2d-pipeline.md +0 -108
- package/dist/docs-raw/platform/admin.md +0 -45
- package/dist/docs-raw/platform/architecture.md +0 -82
- package/dist/docs-raw/platform/auth.md +0 -139
- package/dist/docs-raw/platform/email.md +0 -67
- package/dist/docs-raw/platform/google-oauth-setup.md +0 -88
- package/dist/docs-raw/platform/observability.md +0 -197
- package/dist/docs-raw/platform/projects.md +0 -111
- package/dist/docs-raw/platform/sharing.md +0 -90
- package/dist/docs-raw/product/README.md +0 -39
- package/dist/docs-raw/product/api-as-product-language.md +0 -13
- package/dist/docs-raw/product/business-model.md +0 -15
- package/dist/docs-raw/product/competitive-positioning.md +0 -17
- package/dist/docs-raw/product/creative-manufacturing.md +0 -15
- package/dist/docs-raw/product/founder-story.md +0 -11
- package/dist/docs-raw/product/manufacturing-workflows.md +0 -15
- package/dist/docs-raw/product/onboarding-first-experience.md +0 -256
- package/dist/docs-raw/product/product-loop.md +0 -17
- package/dist/docs-raw/product/strategic-decisions.md +0 -22
- package/dist/docs-raw/product/user-outreach-email-templates.md +0 -161
- package/dist/docs-raw/product/user-segments.md +0 -15
- package/dist/docs-raw/product/vision.md +0 -26
- package/dist/docs-raw/rl-environments.md +0 -350
- package/dist/docs-raw/runbook.md +0 -611
- package/dist-cli/check-compiler-U5SOPN7X.js.map +0 -1
- package/dist-cli/check-query-propagation-XOKNSSYU.js.map +0 -1
- package/dist-cli/chunk-EXWGNL6K.js.map +0 -1
- package/dist-cli/forgecad.js.map +0 -1
- package/dist-cli/forgecad_geometry-GYVNKPIE.js.map +0 -1
- package/dist-cli/solver-46FFSK2U.js.map +0 -1
- package/dist-skill/SKILL-dev.md +0 -145
- package/dist-skill/docs-dev/API/core/concepts.md +0 -118
- package/dist-skill/docs-dev/CLI.md +0 -677
- package/dist-skill/docs-dev/agent-native-api.md +0 -27
- package/dist-skill/docs-dev/blueprint-first.md +0 -145
- package/dist-skill/docs-dev/coding-best-practices.md +0 -120
- package/dist-skill/docs-dev/coding.md +0 -340
- package/dist-skill/docs-dev/component-model.md +0 -164
- package/dist-skill/docs-dev/generated/assembly.md +0 -794
- package/dist-skill/docs-dev/generated/core.md +0 -2117
- package/dist-skill/docs-dev/generated/curves.md +0 -2583
- package/dist-skill/docs-dev/generated/lib.md +0 -169
- package/dist-skill/docs-dev/generated/output.md +0 -247
- package/dist-skill/docs-dev/generated/sdf.md +0 -446
- package/dist-skill/docs-dev/generated/sheet-metal.md +0 -504
- package/dist-skill/docs-dev/generated/sketch.md +0 -1811
- package/dist-skill/docs-dev/generated/viewport.md +0 -585
- package/dist-skill/docs-dev/generated/wood.md +0 -108
- package/dist-skill/docs-dev/guides/coordinate-system.md +0 -46
- package/dist-skill/docs-dev/guides/geometry-conventions.md +0 -52
- package/dist-skill/docs-dev/guides/inspection-bundles.md +0 -485
- package/dist-skill/docs-dev/guides/joint-design.md +0 -78
- package/dist-skill/docs-dev/guides/modeling-recipes.md +0 -78
- package/dist-skill/docs-dev/guides/positioning.md +0 -161
- package/dist-skill/docs-dev/guides/skill-maintenance.md +0 -161
- package/dist-skill/docs-dev/internals/backend-vocabulary.md +0 -35
- package/dist-skill/docs-dev/internals/compiler.md +0 -307
- package/dist-skill/docs-dev/internals/constraint-solver-quality.md +0 -161
- package/dist-skill/docs-dev/internals/constraint-solver.md +0 -176
- package/dist-skill/docs-dev/internals/sketch-2d-pipeline.md +0 -108
- package/dist-skill/library/forgecad-image-replicator/scripts/compare_images.mjs +0 -289
package/dist/docs-raw/runbook.md
DELETED
|
@@ -1,611 +0,0 @@
|
|
|
1
|
-
# ForgeCAD Hosted Service — Runbook
|
|
2
|
-
|
|
3
|
-
Operational reference for running, testing, and troubleshooting the forgecad.io hosted service.
|
|
4
|
-
|
|
5
|
-
For the full documentation index see [INDEX.md](./INDEX.md).
|
|
6
|
-
For environment variables, Docker setup, and deployment details see [deployment.md](deployment.md).
|
|
7
|
-
For dashboards, logs, metrics, and observability access see [platform/observability.md](platform/observability.md).
|
|
8
|
-
For releasing new versions see [RELEASING.md](./RELEASING.md).
|
|
9
|
-
For platform feature docs (auth, projects, sharing, admin, email) see [platform/](./platform/).
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Quick Reference
|
|
14
|
-
|
|
15
|
-
| What | Command |
|
|
16
|
-
|------|---------|
|
|
17
|
-
| Start local DB | `npm run dev:db` |
|
|
18
|
-
| Stop local DB | `npm run dev:db:stop` |
|
|
19
|
-
| Start API server | `npm run dev:server` |
|
|
20
|
-
| Start frontend (with API proxy) | `npm run dev:studio` |
|
|
21
|
-
| Run API tests | `bash scripts/test-shares-api.sh` |
|
|
22
|
-
| Run unit tests | `npm run test:unit` |
|
|
23
|
-
| Run full test suite | `npm test` |
|
|
24
|
-
| Health check | `curl http://localhost:5174/api/health` |
|
|
25
|
-
| SSH to production | `ssh hetzner` |
|
|
26
|
-
| Open observability UI | Connect to Tailscale, then open `http://100.118.68.93:3000` |
|
|
27
|
-
| Check observability stack | `bash scripts/prod/observability-status.sh` |
|
|
28
|
-
| Roll back bad web deploy | `npm run prod:rollback -- <VERSION>` |
|
|
29
|
-
| Verify npm tarball in Docker | `npm run release:docker:all` |
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## NPM Release Docker Verification
|
|
34
|
-
|
|
35
|
-
Use this runbook before publishing a CLI release, after unpublishing/rolling back a bad npm version, or whenever a bug only appears in a clean global install.
|
|
36
|
-
|
|
37
|
-
The check builds the exact npm tarball, recreates a clean `node:22-slim` container, copies the tarball and a model into it, installs the tarball globally, and runs `forgecad run` inside the container. Stop immediately if any step fails.
|
|
38
|
-
|
|
39
|
-
### One-command check
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
npm run release:docker:all
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Default behavior:
|
|
46
|
-
|
|
47
|
-
| Setting | Default |
|
|
48
|
-
|---------|---------|
|
|
49
|
-
| Container | `forgecad-release-check` |
|
|
50
|
-
| Docker image | `node:22-slim` |
|
|
51
|
-
| Browser URL | `http://localhost:4173` |
|
|
52
|
-
| Studio port mapping | host `4173` -> container `5173` |
|
|
53
|
-
| Tarball output | `dist-bundles/npm-release-check/forgecad-<version>.tgz` |
|
|
54
|
-
| Smoke model | `examples/api/verification-demo.forge.js` |
|
|
55
|
-
| Run timeout | `20s` |
|
|
56
|
-
|
|
57
|
-
For a known repro model, override the model path:
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
FORGECAD_RELEASE_MODEL=/Users/kostard/Downloads/plant-pot-holder-marble.forge.js \
|
|
61
|
-
npm run release:docker:all
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
To reuse a familiar container name:
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
FORGECAD_RELEASE_CONTAINER=forgecad-debug \
|
|
68
|
-
FORGECAD_RELEASE_MODEL=/Users/kostard/Downloads/plant-pot-holder-marble.forge.js \
|
|
69
|
-
npm run release:docker:all
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### Step-by-step check
|
|
73
|
-
|
|
74
|
-
Run the lane manually when you want to inspect a specific stage:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
npm run release:pack
|
|
78
|
-
npm run release:docker:create
|
|
79
|
-
npm run release:docker:copy
|
|
80
|
-
npm run release:docker:install
|
|
81
|
-
npm run release:docker:run
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
What each step does:
|
|
85
|
-
|
|
86
|
-
| Step | Purpose |
|
|
87
|
-
|------|---------|
|
|
88
|
-
| `release:pack` | Runs `npm pack` and writes the tarball under `dist-bundles/npm-release-check/`. |
|
|
89
|
-
| `release:docker:create` | Removes any existing release-check container and starts a fresh `node:22-slim` container. |
|
|
90
|
-
| `release:docker:copy` | Copies the tarball to `/tmp/forgecad-release.tgz` and the model to `/tmp/<model-name>` in the container. |
|
|
91
|
-
| `release:docker:install` | Runs `npm install -g /tmp/forgecad-release.tgz` inside the container and prints `forgecad --version`. |
|
|
92
|
-
| `release:docker:run` | Runs `forgecad run /tmp/<model-name>` with update checks disabled and a timeout. |
|
|
93
|
-
| `release:docker:studio` | Starts `forgecad studio /tmp --host 0.0.0.0` in the container. Open `http://localhost:4173` on the host. |
|
|
94
|
-
|
|
95
|
-
Expected success signal:
|
|
96
|
-
|
|
97
|
-
```text
|
|
98
|
-
forgecad --version
|
|
99
|
-
# <new version>
|
|
100
|
-
|
|
101
|
-
✓ Objects: ...
|
|
102
|
-
✓ Verifications: ... pass, 0 fail
|
|
103
|
-
✓ Time: ...
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Manual checks inside the container
|
|
107
|
-
|
|
108
|
-
After `release:docker:install`, open a shell for interactive checks:
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
docker exec -it forgecad-release-check bash
|
|
112
|
-
forgecad --version
|
|
113
|
-
forgecad login
|
|
114
|
-
forgecad run /tmp/verification-demo.forge.js
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
If you used a custom container name, replace `forgecad-release-check`.
|
|
118
|
-
|
|
119
|
-
To open Studio in your host browser without changing the internal ForgeCAD port:
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
npm run release:docker:studio
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
Then open:
|
|
126
|
-
|
|
127
|
-
```text
|
|
128
|
-
http://localhost:4173
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
The helper publishes host port `4173` to the container's normal Studio port `5173`, so `forgecad studio` still runs on its default internal port.
|
|
132
|
-
|
|
133
|
-
### Cleanup
|
|
134
|
-
|
|
135
|
-
Remove the release-check container when done:
|
|
136
|
-
|
|
137
|
-
```bash
|
|
138
|
-
npm run release:docker:clean
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
The tarball output directory is under ignored `dist-bundles/`, but it can still consume local disk. Remove it when space is tight:
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
rm -rf dist-bundles/npm-release-check
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Useful overrides
|
|
148
|
-
|
|
149
|
-
| Variable | Use |
|
|
150
|
-
|----------|-----|
|
|
151
|
-
| `FORGECAD_RELEASE_CONTAINER` | Container name to create/use. |
|
|
152
|
-
| `FORGECAD_RELEASE_IMAGE` | Docker image, for example `node:20-slim` or `node:22-slim`. |
|
|
153
|
-
| `FORGECAD_RELEASE_HOST_PORT` | Host browser port, default `4173`. |
|
|
154
|
-
| `FORGECAD_RELEASE_CONTAINER_PORT` | Container Studio port, default `5173`. |
|
|
155
|
-
| `FORGECAD_RELEASE_STUDIO_PROJECT` | Project path inside the container for `release:docker:studio`, default `/tmp`. |
|
|
156
|
-
| `FORGECAD_RELEASE_PACK_DIR` | Local tarball output directory. |
|
|
157
|
-
| `FORGECAD_RELEASE_TARBALL` | Existing tarball to copy instead of the default output path. |
|
|
158
|
-
| `FORGECAD_RELEASE_MODEL` | Model path to copy and run. |
|
|
159
|
-
| `FORGECAD_RELEASE_TIMEOUT_SECONDS` | Timeout for `forgecad run` inside the container. |
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## Local Development Stack
|
|
164
|
-
|
|
165
|
-
### Minimal (editor only, no auth)
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
npm run dev
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
No database, no login. For geometry, sketches, viewer work.
|
|
172
|
-
|
|
173
|
-
### Full stack (auth, projects, sharing)
|
|
174
|
-
|
|
175
|
-
Three terminals:
|
|
176
|
-
|
|
177
|
-
```bash
|
|
178
|
-
# 1. Database
|
|
179
|
-
npm run dev:db
|
|
180
|
-
|
|
181
|
-
# 2. API server (port 5174)
|
|
182
|
-
npm run dev:server
|
|
183
|
-
|
|
184
|
-
# 3. Frontend (port 5173, proxies /api → 5174)
|
|
185
|
-
npm run dev:studio
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Open http://localhost:5173. Dev credentials are hardcoded in `dev:server` — see [deployment.md](deployment.md#local-development).
|
|
189
|
-
|
|
190
|
-
### Verify the stack is healthy
|
|
191
|
-
|
|
192
|
-
```bash
|
|
193
|
-
# API health
|
|
194
|
-
curl -s http://localhost:5174/api/health | python3 -m json.tool
|
|
195
|
-
|
|
196
|
-
# Database
|
|
197
|
-
docker exec forgecad-postgresql-1 psql -U forgecad -d forgecad -c "SELECT count(*) FROM users;"
|
|
198
|
-
|
|
199
|
-
# Migration state
|
|
200
|
-
docker exec forgecad-postgresql-1 psql -U forgecad -d forgecad -c "SELECT * FROM _migrations ORDER BY id;"
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
---
|
|
204
|
-
|
|
205
|
-
## Testing
|
|
206
|
-
|
|
207
|
-
### API tests (end-to-end, from terminal)
|
|
208
|
-
|
|
209
|
-
These scripts exercise the real server — no mocks, real HTTP, real database.
|
|
210
|
-
|
|
211
|
-
| Script | What it tests | Prerequisites |
|
|
212
|
-
|--------|--------------|---------------|
|
|
213
|
-
| `scripts/test-shares-api.sh` | Publish, fetch, update, unpublish, auth enforcement | `dev:db` + `dev:server` |
|
|
214
|
-
|
|
215
|
-
Run:
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
bash scripts/test-shares-api.sh
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
The script registers a fresh test user, runs through the full lifecycle, and cleans up. Each run uses a unique email so it's safe to re-run.
|
|
222
|
-
|
|
223
|
-
### Adding new API test scripts
|
|
224
|
-
|
|
225
|
-
Follow the pattern in `test-shares-api.sh`:
|
|
226
|
-
|
|
227
|
-
1. Name: `scripts/test-<feature>-api.sh`
|
|
228
|
-
2. Check server health first (`/api/health`)
|
|
229
|
-
3. Register a unique test user per run
|
|
230
|
-
4. Use `acurl()` helper for authenticated requests
|
|
231
|
-
5. Assert HTTP status codes and response fields
|
|
232
|
-
6. Clean up (delete created resources)
|
|
233
|
-
7. Print colored pass/fail per step
|
|
234
|
-
|
|
235
|
-
### Unit tests
|
|
236
|
-
|
|
237
|
-
```bash
|
|
238
|
-
npm run test:unit # vitest
|
|
239
|
-
npm test # smoke invariant suite
|
|
240
|
-
npm run test:smoke # same as npm test
|
|
241
|
-
npm run test:full # broader regression sweep
|
|
242
|
-
npm run check:suite # repo invariant suite
|
|
243
|
-
npm run check:suite -- --profile smoke
|
|
244
|
-
npm run test:examples # maintained fast example smoke lane
|
|
245
|
-
npm run test:examples:full # full example catalog sweep
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
### Invariant checks (CLI)
|
|
249
|
-
|
|
250
|
-
```bash
|
|
251
|
-
node dist-cli/forgecad.js check examples
|
|
252
|
-
node dist-cli/forgecad.js check examples --profile smoke
|
|
253
|
-
node dist-cli/forgecad.js check examples --profile full
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
Use the smoke profiles for everyday merge checks; use the full profiles when you want the broader, currently noisier regression sweep.
|
|
257
|
-
|
|
258
|
-
---
|
|
259
|
-
|
|
260
|
-
## Database
|
|
261
|
-
|
|
262
|
-
### Migrations
|
|
263
|
-
|
|
264
|
-
Migrations run automatically on server startup (`server/db/migrate.ts`). The system:
|
|
265
|
-
|
|
266
|
-
1. Maintains a `_migrations` table tracking applied migrations by sequential ID
|
|
267
|
-
2. Runs unapplied migrations in order on boot
|
|
268
|
-
3. Each migration is idempotent SQL (`CREATE TABLE IF NOT EXISTS`, `ALTER ... ADD COLUMN IF NOT EXISTS`)
|
|
269
|
-
|
|
270
|
-
**To add a new migration:** append to the `MIGRATIONS` array in `server/db/migrate.ts`.
|
|
271
|
-
|
|
272
|
-
### Inspect the database locally
|
|
273
|
-
|
|
274
|
-
```bash
|
|
275
|
-
docker exec -it forgecad-postgresql-1 psql -U forgecad -d forgecad
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
Common queries:
|
|
279
|
-
|
|
280
|
-
```sql
|
|
281
|
-
-- List tables
|
|
282
|
-
\dt
|
|
283
|
-
|
|
284
|
-
-- Users
|
|
285
|
-
SELECT id, email, name, role, created_at FROM users;
|
|
286
|
-
|
|
287
|
-
-- Projects
|
|
288
|
-
SELECT id, slug, name, visibility, owner_id FROM projects;
|
|
289
|
-
|
|
290
|
-
-- Shared/published models
|
|
291
|
-
SELECT share_id, filename, title, owner_id, updated_at FROM shared_files;
|
|
292
|
-
|
|
293
|
-
-- Audit log (recent)
|
|
294
|
-
SELECT action, details, created_at FROM audit_log ORDER BY created_at DESC LIMIT 20;
|
|
295
|
-
|
|
296
|
-
-- Migration state
|
|
297
|
-
SELECT * FROM _migrations ORDER BY id;
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### Backup production database
|
|
301
|
-
|
|
302
|
-
Stream a compressed dump directly to your Mac:
|
|
303
|
-
|
|
304
|
-
```bash
|
|
305
|
-
ssh hetzner "docker exec \$(docker ps --filter name=postgres -q) pg_dump -Fc -U JR3CsoTkOQypFSdD forgecad" > ~/forgecad-backup-<label>.dump
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
Use a descriptive label (e.g., `pre-fileids-20260409`). Always take a backup before deploying migrations that modify existing data.
|
|
309
|
-
|
|
310
|
-
### Restore production database
|
|
311
|
-
|
|
312
|
-
```bash
|
|
313
|
-
cat ~/forgecad-backup-<label>.dump | ssh hetzner "docker exec -i \$(docker ps --filter name=postgres -q) pg_restore -U JR3CsoTkOQypFSdD -d forgecad --clean"
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
This drops and recreates all tables from the dump. The app container will need a restart afterward to reconnect.
|
|
317
|
-
|
|
318
|
-
### Reset local database
|
|
319
|
-
|
|
320
|
-
```bash
|
|
321
|
-
npm run dev:db:stop
|
|
322
|
-
docker volume rm forgecad_postgresql-dev-data # or the worktree-specific volume name
|
|
323
|
-
npm run dev:db
|
|
324
|
-
# Server will re-run all migrations on next start
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
---
|
|
328
|
-
|
|
329
|
-
## Production (Hetzner / Kamal)
|
|
330
|
-
|
|
331
|
-
### Access
|
|
332
|
-
|
|
333
|
-
```bash
|
|
334
|
-
ssh hetzner # see ~/.ssh/config for host alias
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
### Observability-first incident workflow
|
|
338
|
-
|
|
339
|
-
Use the observability stack as the primary path for production incidents. Fall back to raw `docker logs` only if the stack itself is degraded.
|
|
340
|
-
|
|
341
|
-
1. Make sure your laptop is connected to Tailscale.
|
|
342
|
-
|
|
343
|
-
2. Check external symptoms first in Uptime Kuma:
|
|
344
|
-
|
|
345
|
-
- `http://100.118.68.93:3001`
|
|
346
|
-
- Confirm whether `https://forgecad.io/` and `https://forgecad.io/api/health` are down, slow, or flapping.
|
|
347
|
-
|
|
348
|
-
3. Open Grafana for quick triage:
|
|
349
|
-
|
|
350
|
-
- `http://100.118.68.93:3000`
|
|
351
|
-
- Use the `ForgeCAD Host Overview` dashboard first to check host pressure, container pressure, and whether observability targets are up.
|
|
352
|
-
- Then switch to `ForgeCAD Web Requests` if the problem looks like throughput collapse, rising 4xx/5xxs, or slow request handling in the web app.
|
|
353
|
-
- Then switch to `ForgeCAD DB Queries` if the issue looks like latency, auth/session churn, admin slowness, or anything else that may be query-bound.
|
|
354
|
-
|
|
355
|
-
4. Use Grafana Explore for logs and metrics:
|
|
356
|
-
|
|
357
|
-
- Select `Loki` for logs.
|
|
358
|
-
- Select `Prometheus` for metrics.
|
|
359
|
-
|
|
360
|
-
Useful Loki queries:
|
|
361
|
-
|
|
362
|
-
```text
|
|
363
|
-
{container=~"forgecad-web-.*|forgecad-backend-web-.*"}
|
|
364
|
-
{container=~"forgecad-web-.*|forgecad-backend-web-.*"} |= "error"
|
|
365
|
-
{container=~"forgecad-web-.*|forgecad-beta-web-.*"} |= "DB slow query"
|
|
366
|
-
{container=~"forgecad-web-.*|forgecad-beta-web-.*"} | json | event="db.query"
|
|
367
|
-
{container=~"forgecad-beta-.*"}
|
|
368
|
-
{container="kamal-proxy"}
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
### Roll back a bad prod web deploy
|
|
372
|
-
|
|
373
|
-
If the latest web deploy is healthy enough for `/api/health` but breaking real
|
|
374
|
-
user flows, roll back to the previous healthy web version immediately:
|
|
375
|
-
|
|
376
|
-
```bash
|
|
377
|
-
ssh hetzner 'docker ps -a --format "{{.Names}}\t{{.Status}}" | grep "^forgecad-web-" | sed -E "s/^forgecad-web-([a-f0-9]+)(_replaced_[^[:space:]]+)?\t/\1\t/"'
|
|
378
|
-
npm run prod:rollback -- <VERSION>
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
Example:
|
|
382
|
-
|
|
383
|
-
```bash
|
|
384
|
-
npm run prod:rollback -- db9c49b058aaa379d9d622456cb249f9b0ddc335
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
After rollback, verify a real user-facing path, not just `/api/health`. For
|
|
388
|
-
auth incidents, a dummy login should return `401 Invalid credentials`, not
|
|
389
|
-
`500`.
|
|
390
|
-
|
|
391
|
-
Useful Prometheus queries:
|
|
392
|
-
|
|
393
|
-
```text
|
|
394
|
-
up
|
|
395
|
-
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes
|
|
396
|
-
100 * (1 - node_filesystem_avail_bytes{mountpoint="/",fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{mountpoint="/",fstype!~"tmpfs|overlay"})
|
|
397
|
-
sum by (container) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))
|
|
398
|
-
sum(rate(forge_http_request_total[$__rate_interval]))
|
|
399
|
-
sum(rate(forge_http_request_total{surface="api",status_class="5xx"}[$__rate_interval]))
|
|
400
|
-
histogram_quantile(0.95, sum by (le) (rate(forge_http_request_duration_seconds_bucket[$__rate_interval])))
|
|
401
|
-
topk(10, sum by (forge_env, method, route) (rate(forge_http_request_total{surface="api"}[$__rate_interval])))
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
5. Check the app health endpoint after any intervention:
|
|
405
|
-
|
|
406
|
-
```bash
|
|
407
|
-
curl -s https://forgecad.io/api/health | python3 -m json.tool
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
6. Use raw Docker inspection only as fallback or to verify what Grafana already suggested:
|
|
411
|
-
|
|
412
|
-
- `docker logs --tail 200 <forgecad-container>`
|
|
413
|
-
- `docker logs --tail 200 <forgecad-backend-container>`
|
|
414
|
-
- `docker ps --format "{{.Names}}\t{{.Status}}"`
|
|
415
|
-
- `df -h / && free -h`
|
|
416
|
-
|
|
417
|
-
Grafana admin credentials live on Hetzner in `/home/kostard/forgecad-observability/.env`.
|
|
418
|
-
|
|
419
|
-
### Find containers
|
|
420
|
-
|
|
421
|
-
```bash
|
|
422
|
-
docker ps --format "{{.Names}}" | grep forge
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
### Logs
|
|
426
|
-
|
|
427
|
-
```bash
|
|
428
|
-
# App logs (recent)
|
|
429
|
-
docker logs --tail 200 <forgecad-container>
|
|
430
|
-
|
|
431
|
-
# Follow live
|
|
432
|
-
docker logs -f <forgecad-container>
|
|
433
|
-
|
|
434
|
-
# Filter for errors
|
|
435
|
-
docker logs <forgecad-container> 2>&1 | grep -i error | tail -20
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
If the observability stack is healthy, prefer Grafana Explore over direct `docker logs` because it gives you cross-container history and labels in one place.
|
|
439
|
-
|
|
440
|
-
### Database access in production
|
|
441
|
-
|
|
442
|
-
```bash
|
|
443
|
-
# Get credentials from the app container's environment
|
|
444
|
-
docker exec <forgecad-container> env | grep POSTGRES
|
|
445
|
-
|
|
446
|
-
# Connect
|
|
447
|
-
docker exec -it <postgres-container> psql -U <USER> -d forgecad
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### Health check
|
|
451
|
-
|
|
452
|
-
```bash
|
|
453
|
-
curl -s https://forgecad.io/api/health | python3 -m json.tool
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
### Verify a deployment landed
|
|
457
|
-
|
|
458
|
-
GitHub Actions deploys production on push to `mainline` by running Kamal against Hetzner. This usually takes 2–5 minutes, depending on image build and pull time.
|
|
459
|
-
|
|
460
|
-
To confirm:
|
|
461
|
-
|
|
462
|
-
```bash
|
|
463
|
-
# 1. Check container was recently recreated (look at the "Up X minutes" status and CreatedAt)
|
|
464
|
-
ssh hetzner 'docker ps --format "{{.Names}}\t{{.CreatedAt}}\t{{.Status}}" | grep -E "^forgecad-" | grep -v postgres'
|
|
465
|
-
|
|
466
|
-
# 2. Check for healthy status
|
|
467
|
-
ssh hetzner 'docker ps --format "{{.Names}}\t{{.Status}}" | grep -E "^forgecad-" | grep -v postgres | grep healthy'
|
|
468
|
-
|
|
469
|
-
# 3. Check startup logs for errors
|
|
470
|
-
ssh hetzner 'docker logs --tail 30 $(docker ps --format "{{.Names}}" | grep -E "^forgecad-" | grep -v postgres) 2>&1'
|
|
471
|
-
|
|
472
|
-
# 4. Hit the health endpoint
|
|
473
|
-
curl -s https://forgecad.io/api/health | python3 -m json.tool
|
|
474
|
-
|
|
475
|
-
# 5. Verify specific code landed (check compiled output, not source)
|
|
476
|
-
ssh hetzner 'docker exec $(docker ps --format "{{.Names}}" | grep -E "^forgecad-" | grep -v postgres) grep -c "YOUR_KEYWORD" /app/dist-server/routes/files.js'
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
Container names change on each deploy — always discover dynamically with `docker ps | grep forgecad`. The app dir is `/app/` with compiled output in `dist/`, `dist-server/`, `dist-cli/`.
|
|
480
|
-
|
|
481
|
-
### Verify share links work after deploy
|
|
482
|
-
|
|
483
|
-
Share links are a critical user-facing feature. After any deploy that touches shares, files, or database migrations:
|
|
484
|
-
|
|
485
|
-
```bash
|
|
486
|
-
# Hit the share API directly — should return JSON with shareId, code, author
|
|
487
|
-
curl -s https://forgecad.io/api/shares/gUGt8bdvKg | python3 -c "
|
|
488
|
-
import sys, json
|
|
489
|
-
d = json.load(sys.stdin)
|
|
490
|
-
if 'shareId' in d and 'code' in d:
|
|
491
|
-
print(f'OK: share {d[\"shareId\"]} resolves ({len(d[\"code\"])} bytes)')
|
|
492
|
-
else:
|
|
493
|
-
print(f'BROKEN: {d}')
|
|
494
|
-
sys.exit(1)
|
|
495
|
-
"
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
If it prints `BROKEN`, restore the database backup and roll back the deploy.
|
|
499
|
-
|
|
500
|
-
### Restart
|
|
501
|
-
|
|
502
|
-
Kamal normally handles deploys and restarts on push to `mainline`. For a manual restart:
|
|
503
|
-
|
|
504
|
-
```bash
|
|
505
|
-
docker restart $(docker ps --format "{{.Names}}" | grep -E "^forgecad-" | grep -v postgres)
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
### System resources
|
|
509
|
-
|
|
510
|
-
```bash
|
|
511
|
-
df -h # disk
|
|
512
|
-
free -h # memory
|
|
513
|
-
docker stats --no-stream # per-container CPU/memory
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
---
|
|
517
|
-
|
|
518
|
-
## API Endpoints Reference
|
|
519
|
-
|
|
520
|
-
### Public (no auth)
|
|
521
|
-
|
|
522
|
-
| Method | Route | Purpose |
|
|
523
|
-
|--------|-------|---------|
|
|
524
|
-
| GET | `/api/health` | Server health + uptime |
|
|
525
|
-
| GET | `/api/shares/:shareId` | Fetch a published model |
|
|
526
|
-
|
|
527
|
-
### Auth
|
|
528
|
-
|
|
529
|
-
| Method | Route | Purpose |
|
|
530
|
-
|--------|-------|---------|
|
|
531
|
-
| POST | `/api/auth/register` | Create account |
|
|
532
|
-
| POST | `/api/auth/login` | Login (returns cookies) |
|
|
533
|
-
| POST | `/api/auth/refresh` | Refresh access token |
|
|
534
|
-
| POST | `/api/auth/logout` | Clear session |
|
|
535
|
-
| GET | `/api/auth/session` | Current user info |
|
|
536
|
-
| GET | `/api/auth/providers` | OAuth provider URLs |
|
|
537
|
-
| POST | `/api/auth/callback/:provider` | OAuth callback |
|
|
538
|
-
| POST | `/api/auth/forgot-password` | Request password reset |
|
|
539
|
-
| POST | `/api/auth/reset-password` | Apply password reset |
|
|
540
|
-
| GET | `/api/auth/verify-email` | Confirm email |
|
|
541
|
-
| POST | `/api/auth/resend-verification` | Resend verification email |
|
|
542
|
-
|
|
543
|
-
### Projects (all require auth)
|
|
544
|
-
|
|
545
|
-
| Method | Route | Role | Purpose |
|
|
546
|
-
|--------|-------|------|---------|
|
|
547
|
-
| GET | `/api/projects` | — | List user's projects |
|
|
548
|
-
| POST | `/api/projects` | — | Create project |
|
|
549
|
-
| GET | `/api/projects/:id` | viewer | Project details |
|
|
550
|
-
| PATCH | `/api/projects/:id` | owner | Update project |
|
|
551
|
-
| DELETE | `/api/projects/:id` | owner | Delete project |
|
|
552
|
-
| GET | `/api/projects/:id/members` | viewer | List members |
|
|
553
|
-
| POST | `/api/projects/:id/members` | owner | Add member |
|
|
554
|
-
| PATCH | `/api/projects/:id/members/:userId` | owner | Update member role |
|
|
555
|
-
| DELETE | `/api/projects/:id/members/:userId` | owner | Remove member |
|
|
556
|
-
|
|
557
|
-
### Files (all require auth + project role)
|
|
558
|
-
|
|
559
|
-
| Method | Route | Role | Purpose |
|
|
560
|
-
|--------|-------|------|---------|
|
|
561
|
-
| GET | `/api/projects/:id/watch` | viewer | SSE file watcher |
|
|
562
|
-
| GET | `/api/projects/:id/file-ids` | viewer | File ID map (path → fileId) |
|
|
563
|
-
| POST | `/api/projects/:id/save` | editor | Save file (returns fileId) |
|
|
564
|
-
| POST | `/api/projects/:id/delete` | editor | Delete file |
|
|
565
|
-
| POST | `/api/projects/:id/move` | editor | Move/rename file (preserves share links) |
|
|
566
|
-
| POST | `/api/projects/:id/mkdir` | editor | Create directory |
|
|
567
|
-
| GET | `/api/projects/:id/read-binary` | viewer | Download mesh file |
|
|
568
|
-
|
|
569
|
-
### Shares (published models)
|
|
570
|
-
|
|
571
|
-
| Method | Route | Auth | Purpose |
|
|
572
|
-
|--------|-------|------|---------|
|
|
573
|
-
| GET | `/api/shares/:shareId` | none | Fetch published model (public) |
|
|
574
|
-
| GET | `/api/shares` | required | List user's published models |
|
|
575
|
-
| POST | `/api/shares` | required | Publish or update a model |
|
|
576
|
-
| DELETE | `/api/shares/:shareId` | required (owner) | Unpublish |
|
|
577
|
-
|
|
578
|
-
---
|
|
579
|
-
|
|
580
|
-
## Troubleshooting
|
|
581
|
-
|
|
582
|
-
### Server won't start
|
|
583
|
-
|
|
584
|
-
| Symptom | Cause | Fix |
|
|
585
|
-
|---------|-------|-----|
|
|
586
|
-
| `pino-pretty` transport error | Missing dev dependency in worktree | Use `NODE_ENV=production` or install pino-pretty |
|
|
587
|
-
| Port 5174 already in use | Another server instance running | `lsof -i :5174` then kill the PID |
|
|
588
|
-
| `FORGE_DB_URL` missing | Env var not set | Use `npm run dev:server` which sets it automatically |
|
|
589
|
-
| Connection refused on :5432 | Postgres not running | `npm run dev:db` |
|
|
590
|
-
|
|
591
|
-
### Auth issues
|
|
592
|
-
|
|
593
|
-
| Symptom | Cause | Fix |
|
|
594
|
-
|---------|-------|-----|
|
|
595
|
-
| 500 on login/register | Missing `FORGE_JWT_SECRET` | Set it (any string for dev, `openssl rand -base64 32` for prod) |
|
|
596
|
-
| 401 on authenticated endpoints | Expired access token (15 min) | Client should auto-refresh; check refresh token cookie |
|
|
597
|
-
| CORS errors in browser | `FORGE_ALLOWED_ORIGINS` mismatch | Must match the frontend's origin exactly |
|
|
598
|
-
|
|
599
|
-
### Email issues
|
|
600
|
-
|
|
601
|
-
| Symptom | Cause | Fix |
|
|
602
|
-
|---------|-------|-----|
|
|
603
|
-
| No verification/reset email received; logs show `[email] To: user@...` | `RESEND_API_KEY` is empty — falling back to console log | Set `RESEND_API_KEY` in `.kamal/secrets` or production secrets, then redeploy. See [platform/email.md](platform/email.md) |
|
|
604
|
-
|
|
605
|
-
### Database issues
|
|
606
|
-
|
|
607
|
-
| Symptom | Cause | Fix |
|
|
608
|
-
|---------|-------|-----|
|
|
609
|
-
| Migration fails | Schema conflict from manual changes | Reset local DB (see above) |
|
|
610
|
-
| `relation does not exist` | Migrations didn't run | Check `_migrations` table; restart server |
|
|
611
|
-
| Quota errors on file save | User's `storage_used_bytes` exceeded 50MB | Check with `SELECT storage_used_bytes FROM users WHERE ...` |
|