@proveanything/smartlinks 1.16.6 → 1.17.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.
@@ -22,11 +22,12 @@ re-checks the grant **server-side** against the database, so revocation is immed
22
22
  |-------|--------------------|
23
23
  | `read` | read owner-tier data on the proof (attestations, threads, records, cases) |
24
24
  | `comment` | create threads/replies on the proof (guest comments) |
25
+ | `contribute` | add attestations / records to the proof for the life of the grant (temporary contribute access) — optionally held for owner review via `moderate` |
25
26
  | `admin` | read owner-tier data (reserved for elevated share cases; never exposes the platform admin zone) |
26
27
  | `verify_owner` | redeem a shareable ownership **assertion** (not the account) |
27
28
 
28
29
  A grant can carry several scopes, e.g. `['read', 'comment']` for a shareable,
29
- commentable album.
30
+ commentable album, or `['read', 'contribute']` to let someone add photos.
30
31
 
31
32
  ### Security & lifecycle
32
33
 
@@ -124,6 +125,65 @@ Other grant holders (and the owner) see these comments because a `read` grant re
124
125
 
125
126
  ---
126
127
 
128
+ ## Contribute access — let someone add to a proof
129
+
130
+ A `contribute` scope grant is **temporary write access**: the bearer can add
131
+ attestations (a photo, a video reference, a check-in) and app records to the proof
132
+ for the life of the grant — no account or proof claim required. It's the successor
133
+ to ad-hoc "claim windows": properly time-boxed (`expiresAt`), revocable, and voided
134
+ on ownership transfer like every other grant.
135
+
136
+ ```typescript
137
+ // Owner issues a contribute grant that expires in 48h and holds contributions
138
+ // for review before they go public.
139
+ const grant = await proof.createGrant(collectionId, productId, proofId, {
140
+ scope: ['read', 'contribute'],
141
+ moderate: true, // contributions land 'pending'
142
+ expiresAt: new Date(Date.now() + 48 * 60 * 60 * 1000),
143
+ })
144
+
145
+ // Contributor (on the shared link) adds a photo attestation.
146
+ setGrantToken(shareToken)
147
+ await attestation.publicCreate(collectionId, {
148
+ subjectType: 'proof', subjectId: proofId,
149
+ attestationType: 'photo',
150
+ value: { url: 'https://…/photo.jpg' },
151
+ visibility: 'public',
152
+ guestName: 'Sam', // attribution for a public-link bearer
153
+ })
154
+ ```
155
+
156
+ ### Moderation — the two-step review
157
+
158
+ When the grant is issued with `moderate: true`, each contribution is created with
159
+ `moderationStatus: 'pending'` and is **held to the owner**: it is returned only to
160
+ its own author and to owner/admin audiences — never to the public, whatever its
161
+ target `visibility`. The owner reviews and approves (or rejects) it:
162
+
163
+ ```typescript
164
+ // Owner lists what's waiting (owner-tier read = identity or an owner session):
165
+ const { attestations } = await attestation.publicList(collectionId, {
166
+ subjectType: 'proof', subjectId: proofId,
167
+ moderationStatus: 'pending',
168
+ })
169
+
170
+ // Approve → the record goes live at its declared visibility; reject → author+admin only.
171
+ await attestation.moderate(collectionId, attestations[0].id, { decision: 'approve' })
172
+ ```
173
+
174
+ The moderation gate is enforced **server-side** — a front end may badge a pending
175
+ item, but it is the server that withholds it from other viewers. Only
176
+ `moderationStatus` changes on approve/reject; the hashed fact and its chain are
177
+ untouched. Contributions under a grant issued with `moderate: false` (the default)
178
+ go live immediately.
179
+
180
+ > **Media note.** A contributed photo/video is best modelled as an attestation
181
+ > (`attestationType: 'photo'`, `value: { url }`) so it rides this moderation model.
182
+ > The legacy per-proof asset upload path is unchanged and is not grant- or
183
+ > moderation-aware.
184
+
185
+ ---
186
+
127
187
  ## Proof of ownership — `verify_owner`
128
188
 
129
189
  Ownership itself is **not** a grant — it is `proof.ownerId`, established via the
@@ -154,6 +214,7 @@ granted proof (and only that proof):
154
214
  - **Attestations** — `attestation.publicList({ subjectType: 'proof', subjectId })`
155
215
  - **Threads / Records / Cases** — `app.threads.list`, `app.records.*`, `app.cases.list`, and the single-item GETs, filtered to the granted proof
156
216
  - **Thread creation / replies** — with a `comment` scope grant (see below)
217
+ - **Attestation / record creation** — with a `contribute` scope grant (see [Contribute access](#contribute-access--let-someone-add-to-a-proof))
157
218
 
158
219
  The token never exposes the platform `admin` zone, and only reveals `owner`-visibility
159
220
  rows for the granted `proofId`.
@@ -175,14 +236,24 @@ at `sites/{collectionId}/apps/{appId}` — a `grant` branch alongside
175
236
  "requireScope": "comment",
176
237
  "enforce": { "visibility": "owner", "status": "open" }
177
238
  }
239
+ },
240
+ "records": {
241
+ "grant": {
242
+ "allow": true,
243
+ "requireScope": "contribute",
244
+ "enforce": { "visibility": "owner" } // held to the owner until promoted
245
+ }
178
246
  }
179
247
  }
180
248
  }
181
249
  ```
182
250
 
183
- This enables grant-scoped commenting **without** opening up anonymous creation. The
184
- `enforce.visibility: "owner"` keeps comments private to the proof (visible to the
185
- owner and other grant holders, not the wider public).
251
+ This enables grant-scoped commenting and contribution **without** opening up
252
+ anonymous creation. The `enforce.visibility: "owner"` keeps the created object
253
+ private to the proof (visible to the owner and other grant holders, not the wider
254
+ public). Attestation contribution is gated the same way, by the `contribute` scope;
255
+ whether those contributions are held for review is set per-grant with `moderate`,
256
+ not in app config.
186
257
 
187
258
  ---
188
259
 
@@ -200,12 +271,13 @@ namespace proof {
200
271
  function setGrantToken(token: string | undefined): void
201
272
  function getGrantToken(): string | undefined
202
273
 
203
- type GrantScope = 'read' | 'comment' | 'admin' | 'verify_owner'
274
+ type GrantScope = 'read' | 'comment' | 'contribute' | 'admin' | 'verify_owner'
204
275
 
205
276
  interface CreateGrantOptions {
206
277
  scope: GrantScope[] // at least one
207
278
  audience?: { kind: 'public_link' } | { kind: 'named'; email?: string; userId?: string }
208
279
  expiresAt?: Date | string
280
+ moderate?: boolean // 'contribute' only — hold for review
209
281
  }
210
282
 
211
283
  interface RedeemGrantOptions { guestName?: string }
@@ -219,6 +291,7 @@ interface ProofGrant {
219
291
  proofId: string
220
292
  productId?: string | null
221
293
  scope: GrantScope[]
294
+ moderate?: boolean // 'contribute' grants: contributions held for review when true
222
295
  audience: { kind: 'public_link' | 'named'; email?: string; userId?: string }
223
296
  createdBy: string
224
297
  expiresAt?: string | null
package/openapi.yaml CHANGED
@@ -1261,6 +1261,11 @@ paths:
1261
1261
  required: false
1262
1262
  schema:
1263
1263
  type: string
1264
+ - name: moderationStatus
1265
+ in: query
1266
+ required: false
1267
+ schema:
1268
+ $ref: "#/components/schemas/AttestationModerationStatus"
1264
1269
  - name: recordedAfter
1265
1270
  in: query
1266
1271
  required: false
@@ -10237,6 +10242,11 @@ paths:
10237
10242
  required: false
10238
10243
  schema:
10239
10244
  type: string
10245
+ - name: moderationStatus
10246
+ in: query
10247
+ required: false
10248
+ schema:
10249
+ $ref: "#/components/schemas/AttestationModerationStatus"
10240
10250
  - name: recordedAfter
10241
10251
  in: query
10242
10252
  required: false
@@ -10273,7 +10283,7 @@ paths:
10273
10283
  post:
10274
10284
  tags:
10275
10285
  - attestations
10276
- summary: "Create an OWNER-authored attestation (public write) — the counterpart to the admin {@link create}."
10286
+ summary: attestations.publicCreate
10277
10287
  operationId: attestations_publicCreate
10278
10288
  security: []
10279
10289
  parameters:
@@ -10505,6 +10515,43 @@ paths:
10505
10515
  description: Unauthorized
10506
10516
  404:
10507
10517
  description: Not found
10518
+ /public/collection/{collectionId}/attestations/{attestationId}/moderate:
10519
+ post:
10520
+ tags:
10521
+ - attestations
10522
+ summary: Moderate a contributed attestation (proof OWNER by identity, or collection admin).
10523
+ operationId: attestations_moderate
10524
+ security: []
10525
+ parameters:
10526
+ - name: collectionId
10527
+ in: path
10528
+ required: true
10529
+ schema:
10530
+ type: string
10531
+ - name: attestationId
10532
+ in: path
10533
+ required: true
10534
+ schema:
10535
+ type: string
10536
+ responses:
10537
+ 200:
10538
+ description: Success
10539
+ content:
10540
+ application/json:
10541
+ schema:
10542
+ $ref: "#/components/schemas/ModerateAttestationResponse"
10543
+ 400:
10544
+ description: Bad request
10545
+ 401:
10546
+ description: Unauthorized
10547
+ 404:
10548
+ description: Not found
10549
+ requestBody:
10550
+ required: true
10551
+ content:
10552
+ application/json:
10553
+ schema:
10554
+ $ref: "#/components/schemas/ModerateAttestationInput"
10508
10555
  /public/collection/{collectionId}/comm/email/register:
10509
10556
  post:
10510
10557
  tags:
@@ -11115,6 +11162,11 @@ paths:
11115
11162
  required: false
11116
11163
  schema:
11117
11164
  type: string
11165
+ - name: moderationStatus
11166
+ in: query
11167
+ required: false
11168
+ schema:
11169
+ $ref: "#/components/schemas/AttestationModerationStatus"
11118
11170
  - name: recordedAfter
11119
11171
  in: query
11120
11172
  required: false
@@ -18720,6 +18772,10 @@ components:
18720
18772
  type: string
18721
18773
  authorId:
18722
18774
  type: string
18775
+ grantId:
18776
+ type: string
18777
+ moderationStatus:
18778
+ $ref: "#/components/schemas/AttestationModerationStatus"
18723
18779
  metadata:
18724
18780
  type: object
18725
18781
  additionalProperties: true
@@ -18842,10 +18898,29 @@ components:
18842
18898
  metadata:
18843
18899
  type: object
18844
18900
  additionalProperties: true
18901
+ guestName:
18902
+ type: string
18845
18903
  required:
18846
18904
  - subjectType
18847
18905
  - subjectId
18848
18906
  - attestationType
18907
+ ModerateAttestationInput:
18908
+ type: object
18909
+ properties:
18910
+ decision:
18911
+ type: string
18912
+ enum:
18913
+ - approve
18914
+ - reject
18915
+ required:
18916
+ - decision
18917
+ ModerateAttestationResponse:
18918
+ type: object
18919
+ properties:
18920
+ attestation:
18921
+ $ref: "#/components/schemas/Attestation"
18922
+ required:
18923
+ - attestation
18849
18924
  ListAttestationsResponse:
18850
18925
  type: object
18851
18926
  properties:
@@ -18985,6 +19060,8 @@ components:
18985
19060
  type: string
18986
19061
  attestationType:
18987
19062
  type: string
19063
+ moderationStatus:
19064
+ $ref: "#/components/schemas/AttestationModerationStatus"
18988
19065
  recordedAfter:
18989
19066
  type: string
18990
19067
  recordedBefore:
@@ -22783,6 +22860,276 @@ components:
22783
22860
  UploadMessage:
22784
22861
  type: object
22785
22862
  additionalProperties: true
22863
+ FieldMapping:
22864
+ type: object
22865
+ properties:
22866
+ targetPath:
22867
+ type: string
22868
+ sourcePath:
22869
+ type: string
22870
+ transformType:
22871
+ $ref: "#/components/schemas/TransformType"
22872
+ transformExpression:
22873
+ type: string
22874
+ required:
22875
+ - targetPath
22876
+ - transformType
22877
+ FlowConnectionAuth:
22878
+ type: object
22879
+ properties:
22880
+ method:
22881
+ $ref: "#/components/schemas/FlowAuthMethod"
22882
+ headerName:
22883
+ type: string
22884
+ credentialRef:
22885
+ type: string
22886
+ required:
22887
+ - method
22888
+ FlowConnection:
22889
+ type: object
22890
+ properties:
22891
+ baseUrl:
22892
+ type: string
22893
+ sendEndpoint:
22894
+ type: string
22895
+ fetchEndpoint:
22896
+ type: string
22897
+ defaultHeaders:
22898
+ type: object
22899
+ additionalProperties:
22900
+ type: string
22901
+ auth:
22902
+ $ref: "#/components/schemas/FlowConnectionAuth"
22903
+ IntegrationFlowConfig:
22904
+ type: object
22905
+ properties:
22906
+ connection:
22907
+ $ref: "#/components/schemas/FlowConnection"
22908
+ fieldMappings:
22909
+ type: array
22910
+ items:
22911
+ $ref: "#/components/schemas/FieldMapping"
22912
+ IntegrationFlow:
22913
+ type: object
22914
+ properties:
22915
+ id:
22916
+ type: string
22917
+ orgId:
22918
+ type: string
22919
+ collectionId:
22920
+ type: string
22921
+ appId:
22922
+ type: string
22923
+ direction:
22924
+ $ref: "#/components/schemas/FlowDirection"
22925
+ name:
22926
+ type: string
22927
+ status:
22928
+ $ref: "#/components/schemas/FlowStatus"
22929
+ eventTypes:
22930
+ type: array
22931
+ items:
22932
+ type: string
22933
+ schedule:
22934
+ type: string
22935
+ sourceEntity:
22936
+ type: string
22937
+ targetEntity:
22938
+ type: string
22939
+ config:
22940
+ $ref: "#/components/schemas/IntegrationFlowConfig"
22941
+ createdBy:
22942
+ type: string
22943
+ createdAt:
22944
+ type: string
22945
+ updatedAt:
22946
+ type: string
22947
+ deletedAt:
22948
+ type: string
22949
+ lastRunAt:
22950
+ type: string
22951
+ lastRunStatus:
22952
+ type: string
22953
+ lastRunError:
22954
+ type: string
22955
+ lastRunCount:
22956
+ type: number
22957
+ lastPollAt:
22958
+ type: string
22959
+ lastCursor:
22960
+ type: string
22961
+ totalSynced:
22962
+ type: number
22963
+ required:
22964
+ - id
22965
+ - orgId
22966
+ - collectionId
22967
+ - appId
22968
+ - direction
22969
+ - name
22970
+ - status
22971
+ - eventTypes
22972
+ - schedule
22973
+ - sourceEntity
22974
+ - targetEntity
22975
+ - config
22976
+ - createdBy
22977
+ - createdAt
22978
+ - updatedAt
22979
+ CreateFlowInput:
22980
+ type: object
22981
+ properties:
22982
+ appId:
22983
+ type: string
22984
+ direction:
22985
+ $ref: "#/components/schemas/FlowDirection"
22986
+ name:
22987
+ type: string
22988
+ status:
22989
+ $ref: "#/components/schemas/FlowStatus"
22990
+ eventTypes:
22991
+ type: array
22992
+ items:
22993
+ type: string
22994
+ schedule:
22995
+ type: string
22996
+ sourceEntity:
22997
+ type: string
22998
+ targetEntity:
22999
+ type: string
23000
+ config:
23001
+ $ref: "#/components/schemas/IntegrationFlowConfig"
23002
+ required:
23003
+ - appId
23004
+ - direction
23005
+ - name
23006
+ ListFlowsQuery:
23007
+ type: object
23008
+ properties:
23009
+ direction:
23010
+ $ref: "#/components/schemas/FlowDirection"
23011
+ status:
23012
+ $ref: "#/components/schemas/FlowStatus"
23013
+ appId:
23014
+ type: string
23015
+ FlowList:
23016
+ type: object
23017
+ properties:
23018
+ flows:
23019
+ type: array
23020
+ items:
23021
+ $ref: "#/components/schemas/IntegrationFlow"
23022
+ required:
23023
+ - flows
23024
+ RunFlowInput:
23025
+ type: object
23026
+ properties:
23027
+ entityId:
23028
+ type: string
23029
+ RunFlowSummary:
23030
+ type: object
23031
+ properties:
23032
+ flowId:
23033
+ type: string
23034
+ direction:
23035
+ $ref: "#/components/schemas/FlowDirection"
23036
+ records:
23037
+ type: number
23038
+ sent:
23039
+ type: number
23040
+ failed:
23041
+ type: number
23042
+ status:
23043
+ $ref: "#/components/schemas/RunStatus"
23044
+ required:
23045
+ - flowId
23046
+ - direction
23047
+ - records
23048
+ - sent
23049
+ - failed
23050
+ - status
23051
+ RunFlowEnqueued:
23052
+ type: object
23053
+ properties:
23054
+ enqueued:
23055
+ type: object
23056
+ additionalProperties: true
23057
+ flowId:
23058
+ type: string
23059
+ entityId:
23060
+ type: string
23061
+ required:
23062
+ - enqueued
23063
+ - flowId
23064
+ - entityId
23065
+ SecretMeta:
23066
+ type: object
23067
+ properties:
23068
+ ref:
23069
+ type: string
23070
+ name:
23071
+ type: string
23072
+ purpose:
23073
+ type: string
23074
+ hint:
23075
+ type: string
23076
+ keyVersion:
23077
+ type: number
23078
+ createdBy:
23079
+ type: string
23080
+ createdAt:
23081
+ type: string
23082
+ updatedAt:
23083
+ type: string
23084
+ rotatedAt:
23085
+ type: string
23086
+ required:
23087
+ - ref
23088
+ - name
23089
+ - purpose
23090
+ - hint
23091
+ - keyVersion
23092
+ - createdBy
23093
+ - createdAt
23094
+ - updatedAt
23095
+ SecretList:
23096
+ type: object
23097
+ properties:
23098
+ secrets:
23099
+ type: array
23100
+ items:
23101
+ $ref: "#/components/schemas/SecretMeta"
23102
+ required:
23103
+ - secrets
23104
+ SetSecretInput:
23105
+ type: object
23106
+ properties:
23107
+ value:
23108
+ type: string
23109
+ name:
23110
+ type: string
23111
+ purpose:
23112
+ type: string
23113
+ required:
23114
+ - value
23115
+ SetSecretResult:
23116
+ type: object
23117
+ properties:
23118
+ ref:
23119
+ type: string
23120
+ hint:
23121
+ type: string
23122
+ required:
23123
+ - ref
23124
+ - hint
23125
+ ListSecretsQuery:
23126
+ type: object
23127
+ properties:
23128
+ purpose:
23129
+ type: string
23130
+ RunFlowResult:
23131
+ type: object
23132
+ additionalProperties: true
22786
23133
  AdminInteractionsQueryRequest:
22787
23134
  type: object
22788
23135
  properties:
@@ -25832,6 +26179,8 @@ components:
25832
26179
  type: array
25833
26180
  items:
25834
26181
  $ref: "#/components/schemas/GrantScope"
26182
+ moderate:
26183
+ type: boolean
25835
26184
  audience:
25836
26185
  $ref: "#/components/schemas/GrantAudience"
25837
26186
  createdBy:
@@ -25872,6 +26221,8 @@ components:
25872
26221
  expiresAt:
25873
26222
  type: object
25874
26223
  additionalProperties: true
26224
+ moderate:
26225
+ type: boolean
25875
26226
  required:
25876
26227
  - scope
25877
26228
  RedeemGrantOptions:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proveanything/smartlinks",
3
- "version": "1.16.6",
3
+ "version": "1.17.0",
4
4
  "description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "keywords": [
29
29
  "smartlinks",
30
30
  "api",
31
- "authentication",
31
+ "authentication",
32
32
  "traceability",
33
33
  "blockchain",
34
34
  "typescript",