@gemmein/sdk 0.3.0 → 0.3.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/dist/index.cjs CHANGED
@@ -242,8 +242,13 @@ exports.PurchasesClient = PurchasesClient;
242
242
  * are, what the collection's rule says, whether the file is yours, and whether
243
243
  * you still hold whatever the collection requires.
244
244
  *
245
- * That is why the same app code keeps working when a collection later changes
246
- * from public to private and why a refund actually takes a download away.
245
+ * That is why the same app code keeps working across collections, and why a
246
+ * refund takes away a download the buyer had not yet resolved. Two honest
247
+ * bounds: an already-issued link keeps working until it expires (minutes),
248
+ * and a file uploaded while its collection was public keeps its permanent
249
+ * URL even if the rule is later tightened — new uploads seal, old ones are
250
+ * moved only by an owner reseal. Sell access with the rule set from the
251
+ * start, not tightened afterwards.
247
252
  *
248
253
  * Don't store what this returns. Store the reference and call this again.
249
254
  */
package/dist/index.d.cts CHANGED
@@ -242,8 +242,13 @@ export type FileRef = string & {
242
242
  * are, what the collection's rule says, whether the file is yours, and whether
243
243
  * you still hold whatever the collection requires.
244
244
  *
245
- * That is why the same app code keeps working when a collection later changes
246
- * from public to private and why a refund actually takes a download away.
245
+ * That is why the same app code keeps working across collections, and why a
246
+ * refund takes away a download the buyer had not yet resolved. Two honest
247
+ * bounds: an already-issued link keeps working until it expires (minutes),
248
+ * and a file uploaded while its collection was public keeps its permanent
249
+ * URL even if the rule is later tightened — new uploads seal, old ones are
250
+ * moved only by an owner reseal. Sell access with the rule set from the
251
+ * start, not tightened afterwards.
247
252
  *
248
253
  * Don't store what this returns. Store the reference and call this again.
249
254
  */
package/dist/index.d.ts CHANGED
@@ -242,8 +242,13 @@ export type FileRef = string & {
242
242
  * are, what the collection's rule says, whether the file is yours, and whether
243
243
  * you still hold whatever the collection requires.
244
244
  *
245
- * That is why the same app code keeps working when a collection later changes
246
- * from public to private and why a refund actually takes a download away.
245
+ * That is why the same app code keeps working across collections, and why a
246
+ * refund takes away a download the buyer had not yet resolved. Two honest
247
+ * bounds: an already-issued link keeps working until it expires (minutes),
248
+ * and a file uploaded while its collection was public keeps its permanent
249
+ * URL even if the rule is later tightened — new uploads seal, old ones are
250
+ * moved only by an owner reseal. Sell access with the rule set from the
251
+ * start, not tightened afterwards.
247
252
  *
248
253
  * Don't store what this returns. Store the reference and call this again.
249
254
  */
package/dist/index.js CHANGED
@@ -231,8 +231,13 @@ export class PurchasesClient {
231
231
  * are, what the collection's rule says, whether the file is yours, and whether
232
232
  * you still hold whatever the collection requires.
233
233
  *
234
- * That is why the same app code keeps working when a collection later changes
235
- * from public to private and why a refund actually takes a download away.
234
+ * That is why the same app code keeps working across collections, and why a
235
+ * refund takes away a download the buyer had not yet resolved. Two honest
236
+ * bounds: an already-issued link keeps working until it expires (minutes),
237
+ * and a file uploaded while its collection was public keeps its permanent
238
+ * URL even if the rule is later tightened — new uploads seal, old ones are
239
+ * moved only by an owner reseal. Sell access with the rule set from the
240
+ * start, not tightened afterwards.
236
241
  *
237
242
  * Don't store what this returns. Store the reference and call this again.
238
243
  */
package/llms.txt CHANGED
@@ -185,28 +185,47 @@
185
185
  arriving out of order resolve to the newest. The app reads
186
186
  `await g.subscriptions.mine()` → `{ plan, status }` or null, and gates features
187
187
  with `sub?.plan === "pro"`.
188
- - Selling THINGS (one-off purchases a poster, a beat, an ebook): plans are
189
- for subscriptions; products are for things. The builder adds products
190
- (name + Stripe Payment Link) on the same Payments page and picks a
191
- receipts collection (rule `addressed`). The app calls
192
- `await g.payments.buy("poster")` or, when one product covers many items (license
188
+ - Paid ACCESS (entitlements): a collection can require a key your human
189
+ sets `requires: "access:pro"` in the "Unlocked by" row on its Collections
190
+ card and the engine refuses customers without it, under all seven
191
+ rules. (Server secret keys and the owner's console are exempt by design;
192
+ link/expand silently hide gated records rather than naming them.) Keys
193
+ are granted by money: a plan or product lists what it unlocks (e.g.
194
+ `access:pro, access:exports`), the paid webhook grants those keys, and a
195
+ FULL refund or a cancellation revokes exactly what it granted — nothing
196
+ else. A partial refund leaves access in place.
197
+ Owners also grant and revoke by hand (trials, comps, support). Effective
198
+ access is the UNION of a customer's live grants. A signed-in customer
199
+ without the key gets `403 entitlement_required` naming it — show your
200
+ upgrade screen and send them to checkout; never retry. Proof surfaces:
201
+ `await g.purchases.mine()` (everything they paid for, refunds applied,
202
+ with the `grants` each purchase carries) and `await g.subscriptions.mine()`.
203
+ NO credits, NO usage limits, NO seats — access is yes-or-no by design.
204
+ - Selling THINGS (one-off purchases — a beat, an ebook, a course; DIGITAL
205
+ access only — physical goods, shipping, inventory and carts are out of
206
+ scope, said out loud): plans are for subscriptions; products are for
207
+ things. The builder adds products (name + Stripe Payment Link) on the
208
+ same Payments page. The app calls
209
+ `await g.payments.buy("beat")` — or, when one product covers many items (license
193
210
  tiers over a catalog), names the item:
194
- `await g.payments.buy("premium license", { item: "beat_37" })` (display text on
195
- the receipt; the PRICE always comes from the product's Payment Link, so
196
- the item note can never change what's paid). The completed payment writes
197
- a receipt record ADDRESSED to the buyer: only they and the owner read it.
198
- Gate downloads/fulfilment on the receipt, never on the redirect coming
199
- back redirects can be faked, receipts come from Stripe's signed
200
- webhook. Receipts carry
201
- { product, item?, status: "paid"|"refunded", amountTotal (minor units,
202
- as Stripe said), currency, paidAt, deliveryUrl?, paymentRef } deliveryUrl appears
203
- when the builder attached a delivery link to the product (that's how
204
- digital goods deliver themselves; never put a secret download URL in a
205
- public collection). Fulfilment status changes ("shipped") are the owner
206
- editing the receipt in their dashboard; your app just re-reads it.
207
- NO carts, NO quantities one product per checkout by design; a cart is
208
- N checkouts or one bundled product. 404 unknown_product lists what the
209
- app actually sellsuse those names.
211
+ `await g.payments.buy("premium license", { item: "beat_37" })` (display text
212
+ only; the PRICE always comes from the product's Payment Link, so the
213
+ item note can never change what's paid). Gemmein records every completed
214
+ payment itself `await g.purchases.mine()` is the buyer's proof:
215
+ { item, kind, status: "paid"|"part_refunded"|"refunded", amountMinor,
216
+ currency, refundedMinor, grants, paidAt }. A receipts collection (rule
217
+ `addressed`) is OPTIONAL for proof — but TODAY it is REQUIRED for file
218
+ delivery: the file reference only reaches the buyer on the receipt
219
+ record (its `deliveryFile` field, a `file:` refresolve it per reader
220
+ with `g.files.link`, which re-checks access on every mint). Selling a
221
+ file? Configure a receipts collection, or the buyer has no way to reach
222
+ their download. External `deliveryUrl` is a plain handover: Gemmein
223
+ controls who is TOLD, not who can use it. Gate fulfilment on
224
+ the purchase or the entitlement it granted, never on the redirect coming
225
+ back redirects can be faked; the record comes from Stripe's signed
226
+ webhook. NO carts, NO quantities one product per checkout by design; a
227
+ cart is N checkouts or one bundled product. 404 unknown_product lists
228
+ what the app actually sells — use those names.
210
229
  - Drafts on PUBLIC collections (public_read, community): create with the
211
230
  OPTION `{ published: false }` → hidden from every reader except its
212
231
  author and the owner, server-enforced; publish with
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gemmein/sdk",
3
- "version": "0.3.0",
4
- "description": "Gemmein SDK \u2014 passwordless auth, safe storage, and Stripe-driven record flips for AI-built apps. Small enough that one prompt teaches the whole API.",
3
+ "version": "0.3.2",
4
+ "description": "Gemmein SDK passwordless auth, safe storage, and Stripe-driven record flips for AI-built apps. Small enough that one prompt teaches the whole API.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "./dist/index.cjs",