@civitai/app-sdk 0.71.0 → 0.73.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.
@@ -938,6 +938,25 @@ export type BlockToParentMessage = {
938
938
  multiple?: {
939
939
  max: number;
940
940
  };
941
+ /**
942
+ * Offer only images in a published, non-`Private` post: `true`
943
+ * narrows the `'posted'` library to those. It does not filter by
944
+ * rating or by any other post setting. The `'generated'` library is
945
+ * unaffected. OMIT it (or `false`) for today's behaviour, which also
946
+ * offers images in a `Private` post. Send a boolean or nothing: the
947
+ * host refuses any other value with `{ requestId, error }`.
948
+ *
949
+ * Set it when the pick becomes PUBLIC-FACING, e.g. an App Store
950
+ * sub-listing card image (`imageId` on
951
+ * `POST /api/v1/blocks/sub-listings/upsert`, `app.subListings.upsert`
952
+ * in `@civitai/sdk`), which the store refuses for a non-public image.
953
+ * Leave it off when the pick is a private input (a generation source).
954
+ *
955
+ * 🔴 A HOST THAT PREDATES THIS FIELD IGNORES IT and still offers
956
+ * `Private`-post images, so an app setting it must still handle the
957
+ * store's `image_not_public` refusal.
958
+ */
959
+ publicOnly?: boolean;
941
960
  };
942
961
  } | {
943
962
  type: 'SET_USER_CHECKPOINT';
@@ -29,6 +29,7 @@ export declare const BLOCK_SCOPES: {
29
29
  readonly GOODS_READ_SELF: "goods:read:self";
30
30
  readonly GOODS_PURCHASE_SELF: "goods:purchase:self";
31
31
  readonly APPS_STORE_ITEMS_WRITE: "apps:store:items:write";
32
+ readonly SOCIAL_REACT_SELF: "social:react:self";
32
33
  };
33
34
  export type BlockScopeKey = keyof typeof BLOCK_SCOPES;
34
35
  export type BlockScope = (typeof BLOCK_SCOPES)[BlockScopeKey];
@@ -90,6 +90,13 @@ export const BLOCK_SCOPES = {
90
90
  // Requires a signed-in (non-anonymous) subject. 4-segment, like the shared
91
91
  // storage scopes — see BLOCK_SCOPE_PATTERN below.
92
92
  APPS_STORE_ITEMS_WRITE: 'apps:store:items:write',
93
+ // social:react:self — set the VIEWER'S reaction on an image a block endpoint
94
+ // served the app (civitai/civitai#6144). SENSITIVE (a public, reward-paying
95
+ // reaction under the viewer's name, so a declaring manifest MUST carry a
96
+ // `scopeJustifications` entry) and CONSENT-GATED. Listed here because the
97
+ // canonical schema's `scopes` enum carries it; the server ships the feature
98
+ // behind a dark flag, and this package has no reaction helper yet.
99
+ SOCIAL_REACT_SELF: 'social:react:self',
93
100
  };
94
101
  /**
95
102
  * Format helper for the block-scope shape — 2, 3 OR 4 colon-separated
@@ -304,6 +304,11 @@ export type BlockGenerationSourceImageInfo = BlockSourceImage;
304
304
  *
305
305
  * The request's `sources` narrows the picker to one of them; omitting it offers
306
306
  * both. Images only — neither library offers video through this picker.
307
+ *
308
+ * The request's `publicOnly: true` further narrows `'posted'` to images whose
309
+ * post is published and not `Private` (for a public-facing pick such as an App
310
+ * Store sub-listing card image); it does not change `'generated'`. A host that
311
+ * predates `publicOnly` ignores it.
307
312
  */
308
313
  export type BlockImagePickerSource = 'posted' | 'generated';
309
314
  /**
@@ -314,7 +319,8 @@ export type BlockImagePickerSource = 'posted' | 'generated';
314
319
  *
315
320
  * WHAT IS PICKABLE is decided by the host, never by the block:
316
321
  * - `'posted'`: the viewer's own images that are in a published post, fully
317
- * scanned, not flagged, and rated.
322
+ * scanned, not flagged, and rated. A `Private` post counts as published
323
+ * here unless the request set `publicOnly: true`, which leaves those out.
318
324
  * - `'generated'`: the viewer's own succeeded generator outputs that carry a
319
325
  * rating the host recognises.
320
326
  * - Either way the image's rating has to be one the VIEWER'S OWN browsing
@@ -2567,7 +2573,8 @@ export interface BlockStorageIndexes {
2567
2573
  /**
2568
2574
  * A PRIVATE collection — a separate key space per viewer, read and written
2569
2575
  * only by that viewer. Carries none of the shared-only fields (`write`,
2570
- * `counters`, `marks`, `showAuthor`, `dailyWritesPerAuthor`); the canonical
2576
+ * `counters`, `marks`, `showAuthor`, `dailyWritesPerAuthor`,
2577
+ * `ownedModelVersions`); the canonical
2571
2578
  * forbids them here. See {@link BlockStorageSharedCollectionDeclaration} for
2572
2579
  * the fields both kinds share.
2573
2580
  */
@@ -2650,6 +2657,32 @@ export interface BlockStorageSharedCollectionDeclaration {
2650
2657
  * collection viewers write (`write` `'own'` or `'anyone'` only).
2651
2658
  */
2652
2659
  dailyWritesPerAuthor?: number;
2660
+ /**
2661
+ * `write` `'own'` collections only — the canonical refuses it under
2662
+ * `'anyone'`, `'owner'` and `'none'`, and on private collections. Fields of a
2663
+ * document's `data` that, when present, must hold the id of a Civitai model
2664
+ * version owned by the viewer writing the document — for example
2665
+ * `['/workflow/modelVersionId']` for a collection where viewers publish their
2666
+ * own workflows.
2667
+ *
2668
+ * 1 to 4 distinct pointers, each 1 to 4 segments of `/` then a letter or `_`
2669
+ * followed by up to 63 letters, digits or `_` (pattern
2670
+ * `^(/[A-Za-z_][A-Za-z0-9_]{0,63}){1,4}$`). A pointer names one field of
2671
+ * nested objects: it never indexes into an array, and a step through an
2672
+ * array or any other non-object finds nothing.
2673
+ *
2674
+ * On every create and update the server resolves each pointer in the new
2675
+ * `data`. An absent field is allowed. A present one must be a positive
2676
+ * integer naming a model version whose model the writer owns; anything else
2677
+ * — someone else's version, a missing or deleted one, a value that is not a
2678
+ * positive integer — is refused 403 `resource_not_owned`, with
2679
+ * `details.pointer` naming the field, before moderation and before any
2680
+ * write budget is spent. If the ownership lookup itself fails, the write is
2681
+ * refused 503 `service_unavailable` (retryable). Ownership is checked only
2682
+ * when a document is written: documents already stored keep the id if the
2683
+ * model later changes hands or is deleted.
2684
+ */
2685
+ ownedModelVersions?: string[];
2653
2686
  }
2654
2687
  /**
2655
2688
  * One collection declaration — see {@link BlockManifestV1.storage}.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@civitai/app-sdk",
3
- "version": "0.71.0",
3
+ "version": "0.73.0",
4
4
  "description": "OAuth + PKCE, encrypted-cookie sessions, scopes, and orchestrator helpers for building third-party Civitai apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -104,13 +104,14 @@
104
104
  "posts:write:self",
105
105
  "goods:read:self",
106
106
  "goods:purchase:self",
107
- "apps:store:items:write"
107
+ "apps:store:items:write",
108
+ "social:react:self"
108
109
  ]
109
110
  }
110
111
  },
111
112
  "scopeJustifications": {
112
113
  "type": "object",
113
- "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`, `apps:storage:publish`, `posts:write:self`, `apps:store:items:write`) 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.",
114
+ "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`, `apps:storage:publish`, `posts:write:self`, `apps:store:items:write`, `social:react: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.",
114
115
  "additionalProperties": {
115
116
  "type": "string",
116
117
  "minLength": 1,
@@ -468,6 +469,17 @@
468
469
  "description": "RESERVED — civitai.com refuses this field until per-collection write budgets are enabled, so do not declare it yet. Intended meaning: for a shared collection that viewers write (`write` \"own\" or \"anyone\"; refused with \"owner\" or \"none\"), the per-viewer daily budget for creating and updating documents in this collection in place of the platform default, from 1 to 1000, shown to the moderator at review. The bounds are provisional and may change before the field is enabled.",
469
470
  "minimum": 1,
470
471
  "maximum": 1000
472
+ },
473
+ "ownedModelVersions": {
474
+ "type": "array",
475
+ "description": "Shared collections with `write` \"own\" only. Fields of a document's `data` that, when present, must hold a Civitai model version id owned by the viewer writing the document — for example [\"/workflow/modelVersionId\"] for a collection where viewers publish their own workflows. Each entry is a pointer of 1 to 4 segments, each \"/\" then a letter or _ followed by up to 63 letters, digits or _; 1 to 4 distinct pointers. A pointer names one field of nested objects: it never indexes into an array, and a step through an array or any other non-object finds nothing. On every create and update the server resolves each pointer in the new `data`: a field that is absent is allowed; a field that is present must be a positive integer naming a model version whose model the writer owns, and is otherwise refused with 403 `resource_not_owned` — a version that is someone else's, missing or deleted, and a value that is not a positive integer, are all refused the same way. The check runs before moderation and before any write budget is spent. Ownership is checked when a document is written, not afterwards: if the model later changes hands or is deleted, documents already stored keep the id.",
476
+ "minItems": 1,
477
+ "maxItems": 4,
478
+ "uniqueItems": true,
479
+ "items": {
480
+ "type": "string",
481
+ "pattern": "^(/[A-Za-z_][A-Za-z0-9_]{0,63}){1,4}$"
482
+ }
471
483
  }
472
484
  },
473
485
  "allOf": [
@@ -484,7 +496,8 @@
484
496
  "counters": false,
485
497
  "marks": false,
486
498
  "showAuthor": false,
487
- "dailyWritesPerAuthor": false
499
+ "dailyWritesPerAuthor": false,
500
+ "ownedModelVersions": false
488
501
  }
489
502
  }
490
503
  },
@@ -504,6 +517,14 @@
504
517
  },
505
518
  "then": { "properties": { "dailyWritesPerAuthor": false } }
506
519
  },
520
+ {
521
+ "$comment": "ownedModelVersions checks the version against the viewer WRITING the document, so it is declared only where that viewer is always the author: shared collections with write:\"own\" (private collections are refused above).",
522
+ "if": {
523
+ "required": ["write"],
524
+ "properties": { "write": { "enum": ["anyone", "owner", "none"] } }
525
+ },
526
+ "then": { "properties": { "ownedModelVersions": false } }
527
+ },
507
528
  {
508
529
  "$comment": "A write:\"none\" collection is written only through counters and marks, so it must declare at least one.",
509
530
  "if": {