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 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 (trailing newline normalised, nothing else), 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)
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.1",
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"
@@ -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
- **Tolerate exactly one difference: the trailing newline.** Softr sometimes strips the file's final
128
- `\n` on save and sometimes keeps it — stripped on every push on 2026-09-09, kept on every push on
129
- 2026-09-10, same app, same tools. A comparison that demands byte equality will report a phantom
130
- mismatch on some days; one that ignores *all* whitespace will miss the dropped-blank-line case above.
131
- Compare with the trailing newline normalised and nothing else.
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 serialization quirk, and why it is a security issue
158
+ ### The array-argument rejection, and why it is a security issue
156
159
 
157
- **Several tools on this server take an array argument, and some MCP clients serialize it as a JSON
158
- *string* instead.** The API then rejects it with a Jackson error before it reaches any business logic:
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
- It is intermittent, and that is the trap: on 2026-09-09 both tools accepted the array early in a
174
- session and rejected it an hour later, same shapes, same session. Do not conclude from one success
175
- that the path is reliable for the rest of your work.
176
-
177
- **Why the second row is a security problem, not an inconvenience.** Every code push resets the block's
178
- auto-registered Actions to Softr's defaults, and the default for a `genericActions` **ADD_RECORD is
179
- `ALL_USERS`** writable by logged-OUT visitors. The documented remedy is to re-tighten with
180
- `set_vibe_coding_block_action_visibility`. When that call is the one that fails, a routine cosmetic push
181
- silently leaves public write access on the block, and nothing in the push result says so: the push
182
- itself returns `errors: null, warnings: null`. Verified live 2026-09-09 — one push left four ADD_RECORD
183
- actions open across two blocks.
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