@mortar-ai/skill 0.2.0 → 0.3.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/README.md CHANGED
@@ -35,6 +35,12 @@ The skill teaches Claude:
35
35
  - **SDK surface** — the `mortar.from()` / `auth` / `storage` /
36
36
  `realtime` / `compute` / `usage` / `cron` / `queue` / `comms`
37
37
  accessors + the account-scope `AccountClient`; which one to reach for
38
+ - **Transaction boundaries** — atomic row batches and filtered mutations,
39
+ trusted cross-table row + PostgreSQL queue transactions, and why privileged
40
+ transaction clients must never enter browser/mobile bundles
41
+ - **Storage consistency** — immutable physical object versions, atomic metadata
42
+ pointer switches, durable cleanup, and why object storage is not part of a
43
+ PostgreSQL ACID transaction
38
44
  - **CLI commands** — `mortar login / use / db / storage / compute /
39
45
  cron / queue / domains / comms / keys / tokens / topup / usage`
40
46
  - **MCP tools** — the 40 `mortar_*` tools and when an agent should use
package/SKILL.md CHANGED
@@ -1,10 +1,11 @@
1
1
  ---
2
- name: Mortar
3
- description: Required guidance for Fabric apps that need a database, backend, authentication, persistence, file storage, realtime collaboration, cloud functions, or product analytics.
4
- activation: auto
5
- priority: high
6
- triggers:
7
- - keywords: [database, 数据库, backend, 后端, auth, authentication, 登录, 认证, persistence, 持久化, storage, upload, 文件, realtime, 实时, collaboration, compute, cloud, 云端]
2
+ name: mortar
3
+ description: Build or change Fabric applications that use Mortar for database, auth, storage, realtime, compute, or analytics. Use for Mortar schema and provisioning, SDK integration, RLS, transactions, or storage consistency; not for Fabric's own control plane or a different backend.
4
+ metadata:
5
+ activation: auto
6
+ priority: high
7
+ triggers:
8
+ - keywords: [database, 数据库, backend, 后端, auth, authentication, 登录, 认证, persistence, 持久化, transaction, 事务, ACID, storage, upload, 文件, realtime, 实时, collaboration, compute, cloud, 云端]
8
9
  ---
9
10
 
10
11
  # Mortar for Fabric applications
@@ -59,8 +60,16 @@ below; if platform provisioning fails, report that platform failure.
59
60
  tenant. Do not edit or create `mortar.config.json`. Do not edit generated
60
61
  `integrations/mortar/types.ts`; Fabric regenerates it from the live schema.
61
62
  4. Run `npm install @mortar-ai/client` if the dependency is absent, then write app
62
- code using the injected singleton.
63
- 5. Type-check and build. Handle every `{ data, error }` result in UI code.
63
+ code using the injected singleton. Atomic batches, server-side filtered
64
+ mutations, and `DatabaseTransactions` require `@mortar-ai/client` 0.8.0 or
65
+ newer. If an existing project needs one of those capabilities and pins an
66
+ older version, update that dependency with npm and let npm update its lockfile;
67
+ do not rewrite unrelated dependencies.
68
+ 5. Before writing a multi-step mutation, choose the supported consistency
69
+ boundary: one-table batches and filtered mutations can use the bundle-safe
70
+ singleton; cross-table row + queue transactions require trusted server code;
71
+ object storage and external services never join a PostgreSQL transaction.
72
+ 6. Type-check and build. Handle every `{ data, error }` result in UI code.
64
73
 
65
74
  Supported migration kinds are `create_table`, `drop_table`, `set_table_access`,
66
75
  `add_column`, `drop_column`, `create_index`, `set_bucket_access`, `deploy_function`, `delete_function`,
@@ -103,13 +112,87 @@ const { data: created, error: insertError } = await mortar
103
112
  .insert({ title: 'Ship', done: false, user_id: userId })
104
113
  .select()
105
114
  .single();
106
-
107
115
  ```
108
116
 
109
117
  Updates and deletes use the same filter chain. Useful operators include `eq`,
110
118
  `neq`, ranges, `like/ilike`, `in`, `is`, `order`, `limit`, `single`, and
111
119
  `maybeSingle`.
112
120
 
121
+ ### Atomic row mutations
122
+
123
+ Pass an array when every insert or upsert must succeed or fail together. Mortar
124
+ sends at most 200 rows in one request and executes the batch in one
125
+ tenant-scoped PostgreSQL transaction. For upsert, a row with an `id` replaces
126
+ that row's data; a row without an `id` inserts. Do not use a loop or
127
+ `Promise.all` when partial completion would break an invariant.
128
+
129
+ ```ts
130
+ const { data: createdTodos, error: batchError } = await mortar
131
+ .from('todos')
132
+ .insert([
133
+ { title: 'Prepare', done: false, user_id: userId },
134
+ { title: 'Ship', done: false, user_id: userId },
135
+ ])
136
+ .select();
137
+ if (batchError) throw new Error(batchError.message);
138
+
139
+ const { data: changedTodos, error: updateError } = await mortar
140
+ .from('todos')
141
+ .update({ done: true })
142
+ .eq('user_id', userId)
143
+ .eq('archived', false)
144
+ .select();
145
+ if (updateError) throw new Error(updateError.message);
146
+ ```
147
+
148
+ Filtered `update` and `delete` select and mutate all matching rows inside one
149
+ server-side transaction. Do not pre-select IDs and then update/delete them one
150
+ at a time: that creates a race and loses the all-or-nothing guarantee. Chain
151
+ `.select()` only when the app needs the affected rows returned.
152
+
153
+ ### Cross-table transactions are server-only
154
+
155
+ `DatabaseTransactions` can atomically combine up to 200 cross-table row
156
+ `insert` / by-ID `update` / by-ID `delete` operations and PostgreSQL-backed
157
+ queue `enqueue` operations. It is intentionally not attached to the injected
158
+ `mortar` singleton and requires an `app` or `admin` key. Its `execute` method
159
+ throws on failure, so use `try`/`catch`, not a `{ data, error }` envelope.
160
+
161
+ ```ts
162
+ import { DatabaseTransactions } from '@mortar-ai/client';
163
+
164
+ const transactions = new DatabaseTransactions(serverOnlyMortarOptions);
165
+
166
+ try {
167
+ const results = await transactions.execute([
168
+ { op: 'insert', table: 'orders', data: { customer_id: customerId, total } },
169
+ { op: 'enqueue', type: 'send_receipt', payload: { customer_id: customerId } },
170
+ ]);
171
+ console.log(results);
172
+ } catch (error) {
173
+ // Nothing committed. Report or retry the whole idempotent operation.
174
+ throw error;
175
+ }
176
+ ```
177
+
178
+ Never instantiate `DatabaseTransactions` in Web, Desktop renderer,
179
+ Keel/React Native, or WeChat client code. Never add an app/admin key to a
180
+ client-side environment variable or source file. Use this API only in an
181
+ already-approved trusted server environment that holds the key. If a Fabric
182
+ project has no such path, report cross-table ACID as unsupported instead of
183
+ simulating it with several public-client calls. A transactional queue enqueue
184
+ also requires Mortar's PostgreSQL queue backend; otherwise the whole request
185
+ fails without committing row changes.
186
+
187
+ ### Exact ACID boundary
188
+
189
+ Mortar provides true ACID only for work executed in the same tenant-scoped
190
+ PostgreSQL transaction: atomic row batches, filtered row mutations, and the
191
+ trusted cross-table row + PostgreSQL queue API above. Object storage,
192
+ compute/functions, communications providers, analytics delivery, and other
193
+ external systems do not participate in that transaction. Never describe a
194
+ workflow spanning them as one ACID transaction or claim two-phase commit.
195
+
113
196
  ## App-user authentication
114
197
 
115
198
  Auth sessions are persisted and attached to later database, storage, realtime,
@@ -153,6 +236,22 @@ const { data: signed, error: signError } = await bucket.createSignedUrl(path, 36
153
236
  const { error: removeError } = await bucket.remove([path]);
154
237
  ```
155
238
 
239
+ Applications address files by their stable logical `path`. Mortar stores new
240
+ uploads under immutable internal physical versions, then atomically switches
241
+ its PostgreSQL metadata pointer and durably schedules orphan/replaced versions
242
+ for retryable cleanup. Never construct, persist, or expose Mortar's internal
243
+ physical object key. Existing logical paths remain compatible, and application
244
+ projects do not run or author the platform storage migration.
245
+
246
+ This protocol keeps Mortar's own file metadata from pointing at a partial
247
+ upload, but it does not make a separate application row and an object upload
248
+ one transaction. When a business row must reference a file, generate an
249
+ unguessable logical key. For a simple workflow, upload first and write the
250
+ business row only after upload succeeds. For recoverable workflows, create a
251
+ row with a stable idempotency key and `pending` state, upload, then mark it
252
+ `ready`; reconcile stale rows to `failed` or retry them. Do not issue a database
253
+ write and `bucket.upload()` concurrently and call the result atomic.
254
+
156
255
  Downloads mint a short-lived URL and fetch the object directly from the storage
157
256
  backend. Reuse `signed.signedUrl` until it nears expiry when rendering media.
158
257
  Prefer the signed URL directly in `<img src>`, `<video src>`, or `<audio src>`;
package/manifest.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "id": "mortar",
4
- "version": "0.2.0",
5
- "content_sha256": "sha256:dd11d5e635f47e64303927fd4af21b0f8a9aef8836a17c3a592eecb69cc75325",
4
+ "version": "0.3.0",
5
+ "content_sha256": "sha256:c69dab74ad4a377086c0c883c4d400770600738de2741778fad21ec27e925f27",
6
6
  "source_repo": "liamxujia/appunvs",
7
7
  "source_path": "mortar/skill/SKILL.md",
8
8
  "distributions": [
@@ -11,6 +11,6 @@
11
11
  ],
12
12
  "npm": {
13
13
  "package": "@mortar-ai/skill",
14
- "version": "0.2.0"
14
+ "version": "0.3.0"
15
15
  }
16
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mortar-ai/skill",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Agent skill package for building Fabric applications on Mortar (BaaS), distributed from one versioned SKILL.md with a content-addressed manifest.",
5
5
  "main": "index.js",
6
6
  "files": ["SKILL.md", "manifest.json", "index.js", "README.md"],