softr-vibe-coding 2.8.1 → 2.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/CHANGELOG.md +3 -0
- package/SKILL.md +1 -1
- package/package.json +1 -1
- package/references/softr-mcp.md +30 -22
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,9 @@ All notable changes to this skill are documented here. Versions follow [Semantic
|
|
|
4
4
|
|
|
5
5
|
Entries from 1.3.1 onward are generated automatically from git commit subjects between version bumps (see `.github/workflows/publish.yml`). Entries before 1.3.1 were backfilled by hand from the existing commit history.
|
|
6
6
|
|
|
7
|
+
## [2.8.2] - 2026-09-10
|
|
8
|
+
- Corrections on evidence: Softr never strips the trailing newline; the array-argument rejection was client-side stringification, not an empty server schema (2.8.2)
|
|
9
|
+
|
|
7
10
|
## [2.8.1] - 2026-09-10
|
|
8
11
|
- Verifying a push: errors:null is not proof — fetch-back byte-compare, deployed==disk pre-check, two-block swaps (2.8.1)
|
|
9
12
|
- Inventory + keyboard-picker snippet reconciled with the shipped projects-table shape
|
package/SKILL.md
CHANGED
|
@@ -89,7 +89,7 @@ You generate complete, production-ready Softr Vibe Coding blocks as TypeScript R
|
|
|
89
89
|
- Static block: no hardcoded user-visible copy — every string/image/link is an editable setting (see [references/editable-settings.md](references/editable-settings.md#granularity-doctrine-settings-first-static-blocks))
|
|
90
90
|
- Array-setting rows keyed by **index**, never by a builder-editable field value
|
|
91
91
|
- Media settings that may start empty (`src: ""`) gated with a conditional render or placeholder — never an unconditional `<img src={setting.src}>`
|
|
92
|
-
- **Deploying through the MCP:** `errors: null` on a push is not proof — fetch the block's `sourceCode` back and byte-compare it to the file you sent
|
|
92
|
+
- **Deploying through the MCP:** `errors: null` on a push is not proof — fetch the block's `sourceCode` back and byte-compare it to the file you sent, trailing newline included (Softr stores exactly what it receives; the one-byte drift we once blamed on it was a chunked read on our side), and prove deployed == disk *before* editing so a Studio-side change is never overwritten. Protocol in [references/softr-mcp.md → Verifying a push](references/softr-mcp.md#verifying-a-push--the-deployed-source-is-the-only-proof)
|
|
93
93
|
|
|
94
94
|
## What to Clarify
|
|
95
95
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "softr-vibe-coding",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.2",
|
|
4
4
|
"description": "Claude Code skill for generating production-ready Softr Vibe Coding blocks (JSX). Installs into ~/.claude/skills/ and auto-updates on each Claude Code session.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"softr-vibe-coding": "./bin/cli.js"
|
package/references/softr-mcp.md
CHANGED
|
@@ -124,11 +124,14 @@ unverified until you have pulled the source back down and compared it.
|
|
|
124
124
|
3. Push the **entire** file.
|
|
125
125
|
4. **Fetch it back and compare again.** Identical, or you are not done: diff, fix, re-push.
|
|
126
126
|
|
|
127
|
-
**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
**Compare byte for byte, trailing newline included.** Softr stores exactly what it receives: across
|
|
128
|
+
58 push→fetch pairs between 2026-08-26 and 2026-09-10 (14 blocks, 16–161 KB each) the fetched
|
|
129
|
+
`sourceCode` was byte- and MD5-identical to the text sent, including two pushes sent *without* a
|
|
130
|
+
final newline and stored without one. The "deployed block is one byte shorter" we chased on
|
|
131
|
+
2026-09-09 was our own read: an agent that reads a large file in chunks can drop the final
|
|
132
|
+
newline (or a blank line at a chunk boundary) before transmission. A comparison that normalises
|
|
133
|
+
the trailing newline hides exactly that class of error — so do not normalise anything; a mismatch
|
|
134
|
+
means re-send, whatever the byte.
|
|
132
135
|
|
|
133
136
|
**One file, two blocks, two datasource pairs.** When the same source is deployed to two pages, the
|
|
134
137
|
local file holds ONE page's `datasource.define()` pair. Push it as-is to that block; for the other,
|
|
@@ -152,35 +155,40 @@ default permissions (see the next section for why that can be a security problem
|
|
|
152
155
|
the restoration). If page-level visibility is the access control in your app, record that decision
|
|
153
156
|
so nobody chases the reset after every round; if it is not, re-tighten and read back.
|
|
154
157
|
|
|
155
|
-
### The array-argument
|
|
158
|
+
### The array-argument rejection, and why it is a security issue
|
|
156
159
|
|
|
157
|
-
**Several tools
|
|
158
|
-
|
|
160
|
+
**Several workspace-server tools take an array argument, and a call that sends it as a JSON *string*
|
|
161
|
+
is rejected** by Jackson before it reaches any business logic:
|
|
159
162
|
|
|
160
163
|
```
|
|
161
164
|
Cannot deserialize value of type `java.util.ArrayList<java.util.Map<String,Object>>`
|
|
162
165
|
from String value (token `JsonToken.VALUE_STRING`)
|
|
163
166
|
```
|
|
164
167
|
|
|
165
|
-
Root cause: the server advertises an **empty schema** for its tools (`{"type":"object"}`, no property
|
|
166
|
-
definitions), so a client has no type information to serialize against. Confirmed 2026-09-09 on:
|
|
167
|
-
|
|
168
168
|
| Tool | Array argument | Fallback if it fails |
|
|
169
169
|
|---|---|---|
|
|
170
170
|
| `update_vibe_coding_block_code_search_replace` | `operations` | Use `update_vibe_coding_block_code` (full replace) |
|
|
171
171
|
| `set_vibe_coding_block_action_visibility` | `updates` | **NONE — a human must fix it in Studio** |
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
173
|
+
**Where the string comes from — corrected 2026-09-10.** The first write-up of this (2026-09-09)
|
|
174
|
+
blamed the server for advertising an empty schema. The transcripts say otherwise: the workspace
|
|
175
|
+
server's schema declares both parameters as `type: array`, all 13 rejected calls had sent a JSON
|
|
176
|
+
string, and all 84 successful calls to the same two tools had sent a real array — same day, same
|
|
177
|
+
shapes, different payload type. The stringification happened on the client side, most likely on
|
|
178
|
+
calls made while the tool definitions had not been loaded into the model's context (deferred
|
|
179
|
+
schemas), so there was no type to serialise against. **Load the tool's schema before calling it,
|
|
180
|
+
and pass arrays as arrays.** (Empty schemas are real on Softr's *per-application* MCP servers —
|
|
181
|
+
every tool there is advertised as `{"type":"object"}` with a name-only description — but the
|
|
182
|
+
workspace server is not affected.)
|
|
183
|
+
|
|
184
|
+
**Why the second row is a security problem, not an inconvenience.** Every code push resets the
|
|
185
|
+
block's auto-registered Actions to Softr's defaults, and the default for a `genericActions`
|
|
186
|
+
**ADD_RECORD is `ALL_USERS`** — writable by logged-OUT visitors — while UPDATE_RECORD and
|
|
187
|
+
DELETE_RECORD default to `LOGGED_IN_USERS` in the same response. The documented remedy is to
|
|
188
|
+
re-tighten with `set_vibe_coding_block_action_visibility`. When that call is the one that fails, a
|
|
189
|
+
routine cosmetic push silently leaves public write access on the block, and nothing in the push
|
|
190
|
+
result says so: the push itself returns `errors: null, warnings: null`. Verified live 2026-09-09 —
|
|
191
|
+
one push left four ADD_RECORD actions open across two blocks.
|
|
184
192
|
|
|
185
193
|
**So treat permission restoration as a step that must be VERIFIED, never assumed:**
|
|
186
194
|
|