@civitai/app-sdk 0.51.2 → 0.52.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/dist/blocks/index.d.ts
CHANGED
|
@@ -77,5 +77,5 @@ export { isModelSlotContext, isPageSlotContext } from './types.js';
|
|
|
77
77
|
* in `types.ts` for which of the two it uses and why.
|
|
78
78
|
*/
|
|
79
79
|
export { isSignedIn } from './types.js';
|
|
80
|
-
export type { BlockContext, KnownSlotId, ModelSlotId, PageSlotContext, PageSlotId, UnknownSlotContext, BlockManifest, BlockManifestV1, BlockSettings, BlockToken, ContentRating, ManifestBooleanField, ManifestIframe, ManifestNumberField, ManifestPage, ManifestPreview, ManifestSettingField, ManifestSettings, ManifestStringField, ManifestTarget, ModelSlotContext, SettingScope, SettingWidget, Theme, ViewerInfo, BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockSourceImage, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockPendingImageInfo, BlockImageScanResult, BlockUploadPurpose, BlockTextToImageParams, BlockWorkflowSnapshot, BuzzAccountType, ShowcaseImage, WorkflowBody, WorkflowBodyTextToImage, WorkflowBodyCustomComfy, WorkflowBodyCustomComfyRecipe, WorkflowBodyCustomComfyInline, InlineComfyNode, WorkflowBodyStep, WorkflowBodyPassThroughStep, WorkflowStatus, BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockViewer, BlockWildcardPack, BlockWildcardPackErrorCode, AppWorkflow, AppWorkflowImage, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockPostSource, BlockCreatePostRequest, BlockCreatePostResult, BlockCreatePostHostError, } from './types.js';
|
|
80
|
+
export type { BlockContext, KnownSlotId, ModelSlotId, PageSlotContext, PageSlotId, UnknownSlotContext, BlockManifest, BlockManifestGood, BlockManifestV1, BlockSettings, BlockToken, ContentRating, ManifestBooleanField, ManifestIframe, ManifestNumberField, ManifestPage, ManifestPreview, ManifestSettingField, ManifestSettings, ManifestStringField, ManifestTarget, ModelSlotContext, SettingScope, SettingWidget, Theme, ViewerInfo, BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockSourceImage, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockPendingImageInfo, BlockImageScanResult, BlockUploadPurpose, BlockTextToImageParams, BlockWorkflowSnapshot, BuzzAccountType, ShowcaseImage, WorkflowBody, WorkflowBodyTextToImage, WorkflowBodyCustomComfy, WorkflowBodyCustomComfyRecipe, WorkflowBodyCustomComfyInline, InlineComfyNode, WorkflowBodyStep, WorkflowBodyPassThroughStep, WorkflowStatus, BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockViewer, BlockWildcardPack, BlockWildcardPackErrorCode, AppWorkflow, AppWorkflowImage, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockPostSource, BlockCreatePostRequest, BlockCreatePostResult, BlockCreatePostHostError, } from './types.js';
|
|
81
81
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/blocks/scopes.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export declare const BLOCK_SCOPES: {
|
|
|
24
24
|
readonly COLLECTIONS_WRITE_SELF: "collections:write:self";
|
|
25
25
|
readonly COLLECTIONS_READ_PRIVATE: "collections:read:private";
|
|
26
26
|
readonly POSTS_WRITE_SELF: "posts:write:self";
|
|
27
|
+
readonly GOODS_READ_SELF: "goods:read:self";
|
|
28
|
+
readonly GOODS_PURCHASE_SELF: "goods:purchase:self";
|
|
27
29
|
};
|
|
28
30
|
export type BlockScopeKey = keyof typeof BLOCK_SCOPES;
|
|
29
31
|
export type BlockScope = (typeof BLOCK_SCOPES)[BlockScopeKey];
|
package/dist/blocks/scopes.js
CHANGED
|
@@ -48,6 +48,20 @@ export const BLOCK_SCOPES = {
|
|
|
48
48
|
// per-post confirm rendering the SERVER'S resolution of the request, and the
|
|
49
49
|
// server re-runs every guard.
|
|
50
50
|
POSTS_WRITE_SELF: 'posts:write:self',
|
|
51
|
+
// goods:* — the DIGITAL GOODS rail (civitai/civitai#5171): the platform sells
|
|
52
|
+
// a manifest-declared entitlement to the viewer for Buzz, on the app's behalf.
|
|
53
|
+
// These were live on the SERVER and in the canonical schema while absent here,
|
|
54
|
+
// so `defineBlock` rejected both and no app scaffolded from this repo could
|
|
55
|
+
// DECLARE them — the hooks that call them were unreachable. Found by the
|
|
56
|
+
// round-0 reachability question on app-starters#489.
|
|
57
|
+
//
|
|
58
|
+
// `goods:read:self` is CONSENT-EXEMPT by design: the read is scoped
|
|
59
|
+
// server-side to the calling app's own appBlockId, so it can only ever return
|
|
60
|
+
// what that app itself sold and there is no third-party data to consent to.
|
|
61
|
+
// `goods:purchase:self` is CONSENT-GATED — money out of the viewer's balance
|
|
62
|
+
// always needs an explicit grant. Do not collapse the two.
|
|
63
|
+
GOODS_READ_SELF: 'goods:read:self',
|
|
64
|
+
GOODS_PURCHASE_SELF: 'goods:purchase:self',
|
|
51
65
|
};
|
|
52
66
|
/**
|
|
53
67
|
* Format helper for the block-scope shape — 3 OR 4 colon-separated lowercase
|
package/dist/blocks/types.d.ts
CHANGED
|
@@ -1402,6 +1402,40 @@ export interface ManifestPreview {
|
|
|
1402
1402
|
description: string;
|
|
1403
1403
|
screenshots?: string[];
|
|
1404
1404
|
}
|
|
1405
|
+
/**
|
|
1406
|
+
* One entry of a manifest's `goods[]`. Mirrors the canonical schema exactly;
|
|
1407
|
+
* `id`, `title` and `priceBuzz` are required there and so are they here.
|
|
1408
|
+
*
|
|
1409
|
+
* 🔴 DECLARED BEFORE `BlockManifestV1`'S DOCBLOCK ON PURPOSE. Inserting an
|
|
1410
|
+
* interface BETWEEN a docblock and the declaration it documents does not just
|
|
1411
|
+
* look untidy — `tsc` emits both comments onto THIS interface in
|
|
1412
|
+
* `dist/blocks/types.d.ts` and leaves `BlockManifestV1` undocumented, so the
|
|
1413
|
+
* published types told a reader that "only `blockId`, `version`, `name`,
|
|
1414
|
+
* `contentRating` and `scopes` are required" about a type with three fields and
|
|
1415
|
+
* different requirements. Keep any new sibling above this comment or below
|
|
1416
|
+
* `BlockManifestV1`.
|
|
1417
|
+
*/
|
|
1418
|
+
export interface BlockManifestGood {
|
|
1419
|
+
/** Lowercase alphanumeric with `-`/`_`, at most 64 chars. Colon-free, because it is composed into a redis key and a ledger external id. */
|
|
1420
|
+
id: string;
|
|
1421
|
+
/** At most 80 chars. */
|
|
1422
|
+
title: string;
|
|
1423
|
+
/** At most 500 chars. */
|
|
1424
|
+
description?: string;
|
|
1425
|
+
/**
|
|
1426
|
+
* Whole Buzz, minimum 2 — at a price of 1 the owner's floored 70% share is
|
|
1427
|
+
* ZERO, so the app would sell an item and earn nothing from it, permanently.
|
|
1428
|
+
*/
|
|
1429
|
+
priceBuzz: number;
|
|
1430
|
+
/**
|
|
1431
|
+
* What the entitlement grants. `app_unlock` marks a one-time unlock of the app
|
|
1432
|
+
* itself; it is RECORDED identically today and the platform does not yet act
|
|
1433
|
+
* on it, so declaring it buys nothing unless you intend that later behaviour.
|
|
1434
|
+
*/
|
|
1435
|
+
kind?: 'good' | 'app_unlock';
|
|
1436
|
+
/** Opaque app payload, carried verbatim onto the entitlement. Never interpreted by the platform. */
|
|
1437
|
+
payload?: Record<string, unknown>;
|
|
1438
|
+
}
|
|
1405
1439
|
/**
|
|
1406
1440
|
* v1 manifest shape. Mirrors `schemas/app-block/v1.json` — keep them in sync.
|
|
1407
1441
|
*
|
|
@@ -1452,6 +1486,23 @@ export interface BlockManifestV1 {
|
|
|
1452
1486
|
* with the canonical schema's `scopeJustifications` (civitai #3195).
|
|
1453
1487
|
*/
|
|
1454
1488
|
scopeJustifications?: Record<string, string>;
|
|
1489
|
+
/**
|
|
1490
|
+
* Optional DIGITAL GOODS catalog — entitlements the platform sells to a viewer
|
|
1491
|
+
* for Buzz on this app's behalf. Manifest-governed and REVIEW-GATED: the
|
|
1492
|
+
* catalog a moderator approves is the catalog that can be sold, and changing a
|
|
1493
|
+
* price means shipping a new version and being re-reviewed.
|
|
1494
|
+
*
|
|
1495
|
+
* Declaring goods is not by itself permission to sell — the manifest must also
|
|
1496
|
+
* carry `goods:purchase:self` in `scopes`.
|
|
1497
|
+
*
|
|
1498
|
+
* 🔴 THE TYPE WAS ABSENT WHILE THE SCHEMA PROPERTY EXISTED, so `defineBlock`'s
|
|
1499
|
+
* documented inline-literal form rejected a `goods` declaration with TS2353
|
|
1500
|
+
* even though Ajv accepted the same manifest from a JSON file. Nothing could
|
|
1501
|
+
* catch that: there is a vendored-schema↔`BLOCK_SCOPES` cross-check but no
|
|
1502
|
+
* schema-properties↔interface-keys check, and the repo's manifest tests cast.
|
|
1503
|
+
* Kept in lockstep with the canonical schema's `goods`.
|
|
1504
|
+
*/
|
|
1505
|
+
goods?: BlockManifestGood[];
|
|
1455
1506
|
/** Optional; the canonical declares no required sub-field. */
|
|
1456
1507
|
iframe?: ManifestIframe;
|
|
1457
1508
|
/** Full-page surface descriptor (W10). */
|
package/dist/manifest/index.d.ts
CHANGED
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
export { defineBlock, SCHEMA_DIVERGENCES, KNOWN_GAPS, loadCanonicalSchema } from './defineBlock.js';
|
|
16
16
|
export type { DefineBlockConfig } from './defineBlock.js';
|
|
17
17
|
export { BlockManifestError } from '../blocks/manifestError.js';
|
|
18
|
-
export type { BlockManifest, BlockManifestV1 } from '../blocks/types.js';
|
|
18
|
+
export type { BlockManifest, BlockManifestGood, BlockManifestV1 } from '../blocks/types.js';
|
|
19
19
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -99,13 +99,15 @@
|
|
|
99
99
|
"collections:read:self",
|
|
100
100
|
"collections:write:self",
|
|
101
101
|
"collections:read:private",
|
|
102
|
-
"posts:write:self"
|
|
102
|
+
"posts:write:self",
|
|
103
|
+
"goods:read:self",
|
|
104
|
+
"goods:purchase:self"
|
|
103
105
|
]
|
|
104
106
|
}
|
|
105
107
|
},
|
|
106
108
|
"scopeJustifications": {
|
|
107
109
|
"type": "object",
|
|
108
|
-
"description": "Per-scope justification: a map of scope-id → free-text rationale explaining WHY the app needs that permission, shown to the moderator during review. REQUIRED for SENSITIVE scopes — any declared scope that can spend or read the viewer's Buzz, read the viewer's private data, or write data other users see (e.g. `ai:write:budgeted`, `social:tip:self`, `buzz:read:self`, `collections:read:private`, `apps:storage:shared:write`, `posts:write:self`) MUST carry a non-empty justification here, or the manifest is rejected at submit time. OPTIONAL for non-sensitive scopes — omit those and the manifest stays valid. Every key MUST be a scope also present in `scopes` (justifications for scopes you don't request are rejected). Each value is a non-empty string of at most 500 characters. The requirement is enforced imperatively by the manifest validator (not expressed as JSON-Schema conditionals here). NOTE: the justification captures the developer's STATED rationale only; the platform does not verify the truth of the claims.",
|
|
110
|
+
"description": "Per-scope justification: a map of scope-id → free-text rationale explaining WHY the app needs that permission, shown to the moderator during review. REQUIRED for SENSITIVE scopes — any declared scope that can spend or read the viewer's Buzz, read the viewer's private data, or write data other users see (e.g. `ai:write:budgeted`, `social:tip:self`, `goods:purchase:self`, `buzz:read:self`, `collections:read:private`, `apps:storage:shared:write`, `posts:write:self`) MUST carry a non-empty justification here, or the manifest is rejected at submit time. OPTIONAL for non-sensitive scopes — omit those and the manifest stays valid. Every key MUST be a scope also present in `scopes` (justifications for scopes you don't request are rejected). Each value is a non-empty string of at most 500 characters. The requirement is enforced imperatively by the manifest validator (not expressed as JSON-Schema conditionals here). NOTE: the justification captures the developer's STATED rationale only; the platform does not verify the truth of the claims.",
|
|
109
111
|
"additionalProperties": {
|
|
110
112
|
"type": "string",
|
|
111
113
|
"minLength": 1,
|
|
@@ -221,6 +223,51 @@
|
|
|
221
223
|
}
|
|
222
224
|
}
|
|
223
225
|
},
|
|
226
|
+
"goods": {
|
|
227
|
+
"type": "array",
|
|
228
|
+
"description": "Optional DIGITAL GOODS catalog — entitlements the platform sells to a viewer on your app's behalf, for Buzz. Manifest-governed and REVIEW-GATED: the catalog a moderator approves is the catalog that can be sold, and changing a price means shipping a new version and being re-reviewed. The platform owns the ledger (who bought what, when, at what price, and its refund state); the good's MEANING is your app's business — read the viewer's entitlements from GET /api/v1/blocks/entitlements and keep the semantics in your own app storage. Declaring goods does not by itself let you sell: the app must also declare the `goods:purchase:self` scope (and `goods:read:self` to read entitlements back), and the viewer must consent. Sales split platform 30% / app owner 70%, paid immediately. Kept in lockstep with the bounds in src/shared/constants/block-goods.constants.ts (a drift-guard test enforces equality); the imperative validator in that same module is authoritative.",
|
|
229
|
+
"maxItems": 32,
|
|
230
|
+
"items": {
|
|
231
|
+
"type": "object",
|
|
232
|
+
"additionalProperties": false,
|
|
233
|
+
"required": ["id", "title", "priceBuzz"],
|
|
234
|
+
"properties": {
|
|
235
|
+
"id": {
|
|
236
|
+
"type": "string",
|
|
237
|
+
"description": "Stable identifier for this good, unique within the manifest. This is what a purchase and an entitlement are keyed by, so changing it in a later version orphans every entitlement already granted under the old id. Lowercase letters, digits, - and _, starting with a letter or digit.",
|
|
238
|
+
"minLength": 1,
|
|
239
|
+
"maxLength": 64,
|
|
240
|
+
"pattern": "^[a-z0-9][a-z0-9_-]*$"
|
|
241
|
+
},
|
|
242
|
+
"title": {
|
|
243
|
+
"type": "string",
|
|
244
|
+
"description": "Human-readable name shown to the viewer at purchase. Non-empty; the server measures the TRIMMED length, so this maxLength is never more permissive than the server.",
|
|
245
|
+
"minLength": 1,
|
|
246
|
+
"maxLength": 80
|
|
247
|
+
},
|
|
248
|
+
"description": {
|
|
249
|
+
"type": "string",
|
|
250
|
+
"description": "Optional one-paragraph explanation of what the viewer gets.",
|
|
251
|
+
"maxLength": 500
|
|
252
|
+
},
|
|
253
|
+
"priceBuzz": {
|
|
254
|
+
"type": "integer",
|
|
255
|
+
"description": "Price in whole Buzz. Buzz has no sub-unit, so this must be a whole number, and the minimum is 2 rather than 1 because the app owner's 70% share is floored — a 1 Buzz item would earn its owner nothing, permanently. Capped so a single purchase can never drain an account; a viewer also has a daily ceiling across every app they have installed, so a purchase can be refused with a clean 4xx even at a legal price. Both bounds are kept in lockstep with BLOCK_GOOD_MIN_PRICE_BUZZ / BLOCK_GOOD_MAX_PRICE_BUZZ in src/shared/constants/block-goods.constants.ts by a drift-guard test.",
|
|
256
|
+
"minimum": 2,
|
|
257
|
+
"maximum": 50000
|
|
258
|
+
},
|
|
259
|
+
"kind": {
|
|
260
|
+
"type": "string",
|
|
261
|
+
"description": "What the entitlement grants, from the platform's point of view. \"good\" (the default) is an ordinary in-app purchase the platform records and does not interpret. \"app_unlock\" marks a one-time unlock of the app itself; it is RECORDED IDENTICALLY today and the platform does NOT yet act on it — the paid-app access gate is a later change that reads this value. Declaring it now buys nothing, so leave it unset unless you intend that later behaviour.",
|
|
262
|
+
"enum": ["good", "app_unlock"]
|
|
263
|
+
},
|
|
264
|
+
"payload": {
|
|
265
|
+
"type": "object",
|
|
266
|
+
"description": "Optional OPAQUE payload copied verbatim onto the entitlement at purchase and handed back to your app unchanged. The platform never reads or interprets it. It is manifest-sourced rather than client-supplied precisely so that what an entitlement carries is something a moderator saw. Must serialize to at most 2048 bytes."
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
},
|
|
224
271
|
"targets": {
|
|
225
272
|
"type": "array",
|
|
226
273
|
"description": "Model-page slot targets. Each target's slotId must be a known registered model slot (not the page slot). Optional for page-only apps.",
|