@proveanything/smartlinks 1.16.5 → 1.16.7
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/api/attestations.d.ts +53 -4
- package/dist/api/attestations.js +60 -3
- package/dist/api/proof.js +3 -0
- package/dist/docs/API_SUMMARY.md +74 -2
- package/dist/docs/attestations.md +28 -0
- package/dist/docs/proof-share-grants.md +78 -5
- package/dist/openapi.yaml +152 -0
- package/dist/types/attestations.d.ts +69 -0
- package/dist/types/proof.d.ts +22 -2
- package/docs/API_SUMMARY.md +74 -2
- package/docs/attestations.md +28 -0
- package/docs/proof-share-grants.md +78 -5
- package/openapi.yaml +152 -0
- package/package.json +1 -1
package/dist/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
|
|
@@ -10270,6 +10280,37 @@ paths:
|
|
|
10270
10280
|
description: Unauthorized
|
|
10271
10281
|
404:
|
|
10272
10282
|
description: Not found
|
|
10283
|
+
post:
|
|
10284
|
+
tags:
|
|
10285
|
+
- attestations
|
|
10286
|
+
summary: attestations.publicCreate
|
|
10287
|
+
operationId: attestations_publicCreate
|
|
10288
|
+
security: []
|
|
10289
|
+
parameters:
|
|
10290
|
+
- name: collectionId
|
|
10291
|
+
in: path
|
|
10292
|
+
required: true
|
|
10293
|
+
schema:
|
|
10294
|
+
type: string
|
|
10295
|
+
responses:
|
|
10296
|
+
200:
|
|
10297
|
+
description: Success
|
|
10298
|
+
content:
|
|
10299
|
+
application/json:
|
|
10300
|
+
schema:
|
|
10301
|
+
$ref: "#/components/schemas/CreateOwnerAttestationResponse"
|
|
10302
|
+
400:
|
|
10303
|
+
description: Bad request
|
|
10304
|
+
401:
|
|
10305
|
+
description: Unauthorized
|
|
10306
|
+
404:
|
|
10307
|
+
description: Not found
|
|
10308
|
+
requestBody:
|
|
10309
|
+
required: true
|
|
10310
|
+
content:
|
|
10311
|
+
application/json:
|
|
10312
|
+
schema:
|
|
10313
|
+
$ref: "#/components/schemas/OwnerAttestationInput"
|
|
10273
10314
|
/public/collection/{collectionId}/attestations/latest:
|
|
10274
10315
|
get:
|
|
10275
10316
|
tags:
|
|
@@ -10474,6 +10515,43 @@ paths:
|
|
|
10474
10515
|
description: Unauthorized
|
|
10475
10516
|
404:
|
|
10476
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"
|
|
10477
10555
|
/public/collection/{collectionId}/comm/email/register:
|
|
10478
10556
|
post:
|
|
10479
10557
|
tags:
|
|
@@ -11084,6 +11162,11 @@ paths:
|
|
|
11084
11162
|
required: false
|
|
11085
11163
|
schema:
|
|
11086
11164
|
type: string
|
|
11165
|
+
- name: moderationStatus
|
|
11166
|
+
in: query
|
|
11167
|
+
required: false
|
|
11168
|
+
schema:
|
|
11169
|
+
$ref: "#/components/schemas/AttestationModerationStatus"
|
|
11087
11170
|
- name: recordedAfter
|
|
11088
11171
|
in: query
|
|
11089
11172
|
required: false
|
|
@@ -18689,6 +18772,10 @@ components:
|
|
|
18689
18772
|
type: string
|
|
18690
18773
|
authorId:
|
|
18691
18774
|
type: string
|
|
18775
|
+
grantId:
|
|
18776
|
+
type: string
|
|
18777
|
+
moderationStatus:
|
|
18778
|
+
$ref: "#/components/schemas/AttestationModerationStatus"
|
|
18692
18779
|
metadata:
|
|
18693
18780
|
type: object
|
|
18694
18781
|
additionalProperties: true
|
|
@@ -18782,6 +18869,58 @@ components:
|
|
|
18782
18869
|
- subjectType
|
|
18783
18870
|
- subjectId
|
|
18784
18871
|
- attestationType
|
|
18872
|
+
OwnerAttestationInput:
|
|
18873
|
+
type: object
|
|
18874
|
+
properties:
|
|
18875
|
+
subjectType:
|
|
18876
|
+
$ref: "#/components/schemas/AttestationSubjectType"
|
|
18877
|
+
subjectId:
|
|
18878
|
+
type: string
|
|
18879
|
+
attestationType:
|
|
18880
|
+
type: string
|
|
18881
|
+
recordedAt:
|
|
18882
|
+
type: string
|
|
18883
|
+
visibility:
|
|
18884
|
+
type: string
|
|
18885
|
+
enum:
|
|
18886
|
+
- public
|
|
18887
|
+
- owner
|
|
18888
|
+
value:
|
|
18889
|
+
type: object
|
|
18890
|
+
additionalProperties: true
|
|
18891
|
+
ownerData:
|
|
18892
|
+
type: object
|
|
18893
|
+
additionalProperties: true
|
|
18894
|
+
unit:
|
|
18895
|
+
type: string
|
|
18896
|
+
source:
|
|
18897
|
+
type: string
|
|
18898
|
+
metadata:
|
|
18899
|
+
type: object
|
|
18900
|
+
additionalProperties: true
|
|
18901
|
+
guestName:
|
|
18902
|
+
type: string
|
|
18903
|
+
required:
|
|
18904
|
+
- subjectType
|
|
18905
|
+
- subjectId
|
|
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
|
|
18785
18924
|
ListAttestationsResponse:
|
|
18786
18925
|
type: object
|
|
18787
18926
|
properties:
|
|
@@ -18791,6 +18930,13 @@ components:
|
|
|
18791
18930
|
$ref: "#/components/schemas/Attestation"
|
|
18792
18931
|
required:
|
|
18793
18932
|
- attestations
|
|
18933
|
+
CreateOwnerAttestationResponse:
|
|
18934
|
+
type: object
|
|
18935
|
+
properties:
|
|
18936
|
+
attestation:
|
|
18937
|
+
$ref: "#/components/schemas/Attestation"
|
|
18938
|
+
required:
|
|
18939
|
+
- attestation
|
|
18794
18940
|
PublicListAttestationsResponse:
|
|
18795
18941
|
type: object
|
|
18796
18942
|
properties:
|
|
@@ -18914,6 +19060,8 @@ components:
|
|
|
18914
19060
|
type: string
|
|
18915
19061
|
attestationType:
|
|
18916
19062
|
type: string
|
|
19063
|
+
moderationStatus:
|
|
19064
|
+
$ref: "#/components/schemas/AttestationModerationStatus"
|
|
18917
19065
|
recordedAfter:
|
|
18918
19066
|
type: string
|
|
18919
19067
|
recordedBefore:
|
|
@@ -25761,6 +25909,8 @@ components:
|
|
|
25761
25909
|
type: array
|
|
25762
25910
|
items:
|
|
25763
25911
|
$ref: "#/components/schemas/GrantScope"
|
|
25912
|
+
moderate:
|
|
25913
|
+
type: boolean
|
|
25764
25914
|
audience:
|
|
25765
25915
|
$ref: "#/components/schemas/GrantAudience"
|
|
25766
25916
|
createdBy:
|
|
@@ -25801,6 +25951,8 @@ components:
|
|
|
25801
25951
|
expiresAt:
|
|
25802
25952
|
type: object
|
|
25803
25953
|
additionalProperties: true
|
|
25954
|
+
moderate:
|
|
25955
|
+
type: boolean
|
|
25804
25956
|
required:
|
|
25805
25957
|
- scope
|
|
25806
25958
|
RedeemGrantOptions:
|
|
@@ -17,6 +17,14 @@ export type AttestationSubjectType = 'container' | 'proof' | 'product' | 'tag' |
|
|
|
17
17
|
* - `'admin'` — visible to admin callers only
|
|
18
18
|
*/
|
|
19
19
|
export type AttestationVisibility = 'public' | 'owner' | 'admin';
|
|
20
|
+
/**
|
|
21
|
+
* Moderation state of an attestation (separate from {@link AttestationVisibility}).
|
|
22
|
+
* - `'approved'` — live; follows its declared visibility (the default)
|
|
23
|
+
* - `'pending'` — awaiting owner review; returned only to its author and to
|
|
24
|
+
* owner/admin audiences, never to the public, whatever its target visibility
|
|
25
|
+
* - `'rejected'` — owner declined; author + admin only
|
|
26
|
+
*/
|
|
27
|
+
export type AttestationModerationStatus = 'approved' | 'pending' | 'rejected';
|
|
20
28
|
/**
|
|
21
29
|
* Resolved audience tier returned by public endpoints.
|
|
22
30
|
* Tells the client which data zones are populated in the response.
|
|
@@ -59,6 +67,19 @@ export interface Attestation {
|
|
|
59
67
|
source?: string;
|
|
60
68
|
/** User ID or service account that recorded the fact */
|
|
61
69
|
authorId?: string;
|
|
70
|
+
/**
|
|
71
|
+
* When authored under a `contribute` grant (rather than by identity), the id of
|
|
72
|
+
* the granting token — provenance for a contributed record. `null`/absent for
|
|
73
|
+
* owner/admin/identity writes.
|
|
74
|
+
*/
|
|
75
|
+
grantId?: string | null;
|
|
76
|
+
/**
|
|
77
|
+
* Moderation gate, orthogonal to {@link visibility} and excluded from the hash
|
|
78
|
+
* chain. `'approved'` (default) is live; `'pending'` is held for owner review
|
|
79
|
+
* (visible only to its author and owner/admin audiences); `'rejected'` was
|
|
80
|
+
* declined. Contributions under a `moderate` grant start `'pending'`.
|
|
81
|
+
*/
|
|
82
|
+
moderationStatus?: AttestationModerationStatus;
|
|
62
83
|
/** Arbitrary extra metadata */
|
|
63
84
|
metadata?: Record<string, any>;
|
|
64
85
|
/** SHA-256 digest of this record (includes `prevHash`) */
|
|
@@ -128,9 +149,51 @@ export interface CreateAttestationInput {
|
|
|
128
149
|
authorId?: string;
|
|
129
150
|
metadata?: Record<string, any>;
|
|
130
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Public attestation write input, used by {@link attestations.publicCreate}.
|
|
154
|
+
*
|
|
155
|
+
* Authorised two ways, same input shape (the server decides from the request):
|
|
156
|
+
* 1. the proof OWNER (Firebase ID token) adds an attestation to their own item;
|
|
157
|
+
* 2. a holder of a `contribute`-scope grant adds one — set the grant token with
|
|
158
|
+
* `setGrantToken(token)` first; for a public-link (anonymous) grant, pass
|
|
159
|
+
* `guestName` for attribution.
|
|
160
|
+
*
|
|
161
|
+
* Restricted vs {@link CreateAttestationInput}: no `adminData` (business-only
|
|
162
|
+
* zone), `visibility` limited to `'public' | 'owner'`, and `authorId` / `grantId`
|
|
163
|
+
* are server-stamped (so they're omitted here). If the contribute grant was issued
|
|
164
|
+
* with `moderate: true`, the created record comes back `moderationStatus: 'pending'`.
|
|
165
|
+
*/
|
|
166
|
+
export interface OwnerAttestationInput {
|
|
167
|
+
subjectType: AttestationSubjectType;
|
|
168
|
+
subjectId: string;
|
|
169
|
+
attestationType: string;
|
|
170
|
+
recordedAt?: string;
|
|
171
|
+
/** `'public'` | `'owner'` only — defaults to `'owner'`. */
|
|
172
|
+
visibility?: 'public' | 'owner';
|
|
173
|
+
value?: Record<string, any>;
|
|
174
|
+
ownerData?: Record<string, any>;
|
|
175
|
+
unit?: string;
|
|
176
|
+
source?: string;
|
|
177
|
+
metadata?: Record<string, any>;
|
|
178
|
+
/**
|
|
179
|
+
* Attribution for an anonymous (public-link) contribute-grant write. Ignored
|
|
180
|
+
* for owner writes and for named-grant writes (attributed to the signed-in uid).
|
|
181
|
+
*/
|
|
182
|
+
guestName?: string;
|
|
183
|
+
}
|
|
184
|
+
/** Owner/admin decision on a pending contributed attestation. */
|
|
185
|
+
export interface ModerateAttestationInput {
|
|
186
|
+
decision: 'approve' | 'reject';
|
|
187
|
+
}
|
|
188
|
+
export interface ModerateAttestationResponse {
|
|
189
|
+
attestation: Attestation;
|
|
190
|
+
}
|
|
131
191
|
export interface ListAttestationsResponse {
|
|
132
192
|
attestations: Attestation[];
|
|
133
193
|
}
|
|
194
|
+
export interface CreateOwnerAttestationResponse {
|
|
195
|
+
attestation: Attestation;
|
|
196
|
+
}
|
|
134
197
|
export interface PublicListAttestationsResponse {
|
|
135
198
|
attestations: Attestation[];
|
|
136
199
|
/** Resolved audience tier; governs which data zones are populated */
|
|
@@ -175,6 +238,12 @@ export interface ListAttestationsParams {
|
|
|
175
238
|
/** Required */
|
|
176
239
|
subjectId: string;
|
|
177
240
|
attestationType?: string;
|
|
241
|
+
/**
|
|
242
|
+
* Filter by moderation state. Primarily for the owner review queue
|
|
243
|
+
* (`moderationStatus: 'pending'`). ANDs with the server's audience gate, so a
|
|
244
|
+
* public caller can never use it to widen access.
|
|
245
|
+
*/
|
|
246
|
+
moderationStatus?: AttestationModerationStatus;
|
|
178
247
|
/** ISO 8601 lower bound (inclusive) */
|
|
179
248
|
recordedAfter?: string;
|
|
180
249
|
/** ISO 8601 upper bound (inclusive) */
|
package/dist/types/proof.d.ts
CHANGED
|
@@ -164,8 +164,16 @@ export type ProofFieldDef = ScopedFieldDef & {
|
|
|
164
164
|
export interface ProofFieldsConfig {
|
|
165
165
|
fields: ProofFieldDef[];
|
|
166
166
|
}
|
|
167
|
-
/**
|
|
168
|
-
|
|
167
|
+
/**
|
|
168
|
+
* What a grant authorises the bearer to do on the proof.
|
|
169
|
+
* - `read` — see owner-tier data
|
|
170
|
+
* - `comment` — post app threads/comments
|
|
171
|
+
* - `contribute` — add records / attestations (temporary contribute access); pair
|
|
172
|
+
* with `moderate` on {@link CreateGrantOptions} to hold contributions for review
|
|
173
|
+
* - `admin` — owner-tier read across the proof
|
|
174
|
+
* - `verify_owner` — redeem an ownership assertion (never the account)
|
|
175
|
+
*/
|
|
176
|
+
export type GrantScope = 'read' | 'comment' | 'contribute' | 'admin' | 'verify_owner';
|
|
169
177
|
/** Who may redeem a grant. */
|
|
170
178
|
export interface GrantAudience {
|
|
171
179
|
kind: 'public_link' | 'named';
|
|
@@ -178,6 +186,11 @@ export interface ProofGrant {
|
|
|
178
186
|
proofId: string;
|
|
179
187
|
productId?: string | null;
|
|
180
188
|
scope: GrantScope[];
|
|
189
|
+
/**
|
|
190
|
+
* `contribute` grants only: when true, records/attestations added under this
|
|
191
|
+
* grant land `pending` (owner-only) until the owner approves them.
|
|
192
|
+
*/
|
|
193
|
+
moderate?: boolean;
|
|
181
194
|
audience: GrantAudience;
|
|
182
195
|
createdBy: string;
|
|
183
196
|
expiresAt?: string | null;
|
|
@@ -200,6 +213,13 @@ export interface CreateGrantOptions {
|
|
|
200
213
|
audience?: GrantAudience;
|
|
201
214
|
/** Optional expiry — a `Date` or ISO string. */
|
|
202
215
|
expiresAt?: Date | string;
|
|
216
|
+
/**
|
|
217
|
+
* Only meaningful with the `contribute` scope: hold contributions made under
|
|
218
|
+
* this grant for owner review (they start `pending` and are owner-only until
|
|
219
|
+
* approved). Ignored for other scopes. Defaults to `false` (contributions live
|
|
220
|
+
* on write).
|
|
221
|
+
*/
|
|
222
|
+
moderate?: boolean;
|
|
203
223
|
}
|
|
204
224
|
export interface RedeemGrantOptions {
|
|
205
225
|
/** Display name to stamp on guest activity when the redeemer is not signed in. */
|
package/docs/API_SUMMARY.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Smartlinks API Summary
|
|
2
2
|
|
|
3
|
-
Version: 1.16.
|
|
3
|
+
Version: 1.16.7 | Generated: 2026-09-09T11:29:21.917Z
|
|
4
4
|
|
|
5
5
|
This is a concise summary of all available API functions and types.
|
|
6
6
|
|
|
@@ -2745,6 +2745,15 @@ interface Attestation {
|
|
|
2745
2745
|
unit?: string
|
|
2746
2746
|
source?: string
|
|
2747
2747
|
authorId?: string
|
|
2748
|
+
* When authored under a `contribute` grant (rather than by identity), the id of
|
|
2749
|
+
* the granting token — provenance for a contributed record. `null`/absent for
|
|
2750
|
+
* owner/admin/identity writes.
|
|
2751
|
+
grantId?: string | null
|
|
2752
|
+
* Moderation gate, orthogonal to {@link visibility} and excluded from the hash
|
|
2753
|
+
* chain. `'approved'` (default) is live; `'pending'` is held for owner review
|
|
2754
|
+
* (visible only to its author and owner/admin audiences); `'rejected'` was
|
|
2755
|
+
* declined. Contributions under a `moderate` grant start `'pending'`.
|
|
2756
|
+
moderationStatus?: AttestationModerationStatus
|
|
2748
2757
|
metadata?: Record<string, any>
|
|
2749
2758
|
contentHash: string
|
|
2750
2759
|
prevHash?: string
|
|
@@ -2797,6 +2806,39 @@ interface CreateAttestationInput {
|
|
|
2797
2806
|
}
|
|
2798
2807
|
```
|
|
2799
2808
|
|
|
2809
|
+
**OwnerAttestationInput** (interface)
|
|
2810
|
+
```typescript
|
|
2811
|
+
interface OwnerAttestationInput {
|
|
2812
|
+
subjectType: AttestationSubjectType
|
|
2813
|
+
subjectId: string
|
|
2814
|
+
attestationType: string
|
|
2815
|
+
recordedAt?: string
|
|
2816
|
+
visibility?: 'public' | 'owner'
|
|
2817
|
+
value?: Record<string, any>
|
|
2818
|
+
ownerData?: Record<string, any>
|
|
2819
|
+
unit?: string
|
|
2820
|
+
source?: string
|
|
2821
|
+
metadata?: Record<string, any>
|
|
2822
|
+
* Attribution for an anonymous (public-link) contribute-grant write. Ignored
|
|
2823
|
+
* for owner writes and for named-grant writes (attributed to the signed-in uid).
|
|
2824
|
+
guestName?: string
|
|
2825
|
+
}
|
|
2826
|
+
```
|
|
2827
|
+
|
|
2828
|
+
**ModerateAttestationInput** (interface)
|
|
2829
|
+
```typescript
|
|
2830
|
+
interface ModerateAttestationInput {
|
|
2831
|
+
decision: 'approve' | 'reject'
|
|
2832
|
+
}
|
|
2833
|
+
```
|
|
2834
|
+
|
|
2835
|
+
**ModerateAttestationResponse** (interface)
|
|
2836
|
+
```typescript
|
|
2837
|
+
interface ModerateAttestationResponse {
|
|
2838
|
+
attestation: Attestation
|
|
2839
|
+
}
|
|
2840
|
+
```
|
|
2841
|
+
|
|
2800
2842
|
**ListAttestationsResponse** (interface)
|
|
2801
2843
|
```typescript
|
|
2802
2844
|
interface ListAttestationsResponse {
|
|
@@ -2804,6 +2846,13 @@ interface ListAttestationsResponse {
|
|
|
2804
2846
|
}
|
|
2805
2847
|
```
|
|
2806
2848
|
|
|
2849
|
+
**CreateOwnerAttestationResponse** (interface)
|
|
2850
|
+
```typescript
|
|
2851
|
+
interface CreateOwnerAttestationResponse {
|
|
2852
|
+
attestation: Attestation
|
|
2853
|
+
}
|
|
2854
|
+
```
|
|
2855
|
+
|
|
2807
2856
|
**PublicListAttestationsResponse** (interface)
|
|
2808
2857
|
```typescript
|
|
2809
2858
|
interface PublicListAttestationsResponse {
|
|
@@ -2882,6 +2931,10 @@ interface ListAttestationsParams {
|
|
|
2882
2931
|
subjectType: AttestationSubjectType
|
|
2883
2932
|
subjectId: string
|
|
2884
2933
|
attestationType?: string
|
|
2934
|
+
* Filter by moderation state. Primarily for the owner review queue
|
|
2935
|
+
* (`moderationStatus: 'pending'`). ANDs with the server's audience gate, so a
|
|
2936
|
+
* public caller can never use it to widen access.
|
|
2937
|
+
moderationStatus?: AttestationModerationStatus
|
|
2885
2938
|
recordedAfter?: string
|
|
2886
2939
|
recordedBefore?: string
|
|
2887
2940
|
limit?: number
|
|
@@ -2946,6 +2999,8 @@ interface AttestationTreeLatestParams {
|
|
|
2946
2999
|
|
|
2947
3000
|
**AttestationVisibility** = `'public' | 'owner' | 'admin'`
|
|
2948
3001
|
|
|
3002
|
+
**AttestationModerationStatus** = `'approved' | 'pending' | 'rejected'`
|
|
3003
|
+
|
|
2949
3004
|
**AttestationAudience** = `'public' | 'owner' | 'admin'`
|
|
2950
3005
|
|
|
2951
3006
|
**AttestationGroupBy** = `'hour' | 'day' | 'week' | 'month'`
|
|
@@ -7541,6 +7596,9 @@ interface ProofGrant {
|
|
|
7541
7596
|
proofId: string
|
|
7542
7597
|
productId?: string | null
|
|
7543
7598
|
scope: GrantScope[]
|
|
7599
|
+
* `contribute` grants only: when true, records/attestations added under this
|
|
7600
|
+
* grant land `pending` (owner-only) until the owner approves them.
|
|
7601
|
+
moderate?: boolean
|
|
7544
7602
|
audience: GrantAudience
|
|
7545
7603
|
createdBy: string
|
|
7546
7604
|
expiresAt?: string | null
|
|
@@ -7559,6 +7617,11 @@ interface CreateGrantOptions {
|
|
|
7559
7617
|
scope: GrantScope[]
|
|
7560
7618
|
audience?: GrantAudience
|
|
7561
7619
|
expiresAt?: Date | string
|
|
7620
|
+
* Only meaningful with the `contribute` scope: hold contributions made under
|
|
7621
|
+
* this grant for owner review (they start `pending` and are owner-only until
|
|
7622
|
+
* approved). Ignored for other scopes. Defaults to `false` (contributions live
|
|
7623
|
+
* on write).
|
|
7624
|
+
moderate?: boolean
|
|
7562
7625
|
}
|
|
7563
7626
|
```
|
|
7564
7627
|
|
|
@@ -7656,7 +7719,7 @@ interface CancelTransferOptions {
|
|
|
7656
7719
|
|
|
7657
7720
|
**ProofFieldDef** = `ScopedFieldDef & { scope?: ProofFieldScope }`
|
|
7658
7721
|
|
|
7659
|
-
**GrantScope** = `'read' | 'comment' | 'admin' | 'verify_owner'`
|
|
7722
|
+
**GrantScope** = `'read' | 'comment' | 'contribute' | 'admin' | 'verify_owner'`
|
|
7660
7723
|
|
|
7661
7724
|
**RedeemGrantResult** = ``
|
|
7662
7725
|
|
|
@@ -9063,6 +9126,15 @@ Tree latest snapshot — most-recent record per type across a container subtree
|
|
|
9063
9126
|
params: ListAttestationsParams) → `Promise<PublicListAttestationsResponse>`
|
|
9064
9127
|
List attestations for a subject (public). Records with `visibility='admin'` are always excluded. Records with `visibility='owner'` are included only when the caller provides a valid Firebase ID token that resolves to the subject owner. The `audience` field in the response indicates the tier that was served. ```typescript const { attestations: records, audience } = await attestations.publicList('coll_123', { subjectType: 'proof', subjectId: 'proof-uuid', }) ```
|
|
9065
9128
|
|
|
9129
|
+
**publicCreate**(collectionId: string,
|
|
9130
|
+
data: OwnerAttestationInput) → `Promise<CreateOwnerAttestationResponse>`
|
|
9131
|
+
Create a public attestation — the counterpart to the admin {@link create}. Authorised two ways, same call (the server decides from the request): 1. the proof OWNER (identity, via `Authorization: Bearer <Firebase ID token>`) adds an attestation to their own item; or 2. a holder of a `contribute`-scope grant adds one — call {@link setGrantToken} with the grant token first; for a public-link (anonymous) grant, pass `guestName` for attribution. Guardrails (server-enforced): `value` + `ownerData` only (`adminData` dropped), `visibility` clamped to `'public' | 'owner'`, `authorId`/`grantId` server-stamped. If the contribute grant was issued with `moderate: true`, the returned record has `moderationStatus: 'pending'` — held to the owner until {@link moderate}. The record joins the same tamper-evident hash chain. POST /public/collection/:collectionId/attestations ```ts // Owner: await attestations.publicCreate('coll_123', { subjectType: 'proof', subjectId: 'proof_1', attestationType: 'condition-report', value: { grade: 'excellent' }, visibility: 'public', }) // Contributor on a shared link: setGrantToken(shareToken) await attestations.publicCreate('coll_123', { subjectType: 'proof', subjectId: 'proof_1', attestationType: 'photo', value: { url }, visibility: 'public', guestName: 'Sam', }) ```
|
|
9132
|
+
|
|
9133
|
+
**moderate**(collectionId: string,
|
|
9134
|
+
attestationId: string,
|
|
9135
|
+
input: ModerateAttestationInput) → `Promise<ModerateAttestationResponse>`
|
|
9136
|
+
Moderate a contributed attestation (proof OWNER by identity, or collection admin). `'approve'` releases it to its declared visibility; `'reject'` keeps it author + admin only. Only the `moderationStatus` changes — the hashed fact and its chain are untouched. Find pending items with {@link publicList} + `moderationStatus: 'pending'`. POST /public/collection/:collectionId/attestations/:attestationId/moderate ```ts await attestations.moderate('coll_123', 'att_uuid', { decision: 'approve' }) ```
|
|
9137
|
+
|
|
9066
9138
|
**publicSummary**(collectionId: string,
|
|
9067
9139
|
params: AttestationSummaryParams) → `Promise<PublicAttestationSummaryResponse>`
|
|
9068
9140
|
Time-series summary (public). Always served at `audience='public'`. Same parameters as the admin version. `attestationType` are required
|
package/docs/attestations.md
CHANGED
|
@@ -159,6 +159,34 @@ The middleware resolves the UID and checks ownership:
|
|
|
159
159
|
|
|
160
160
|
When ownership is confirmed the request is served at `audience='owner'`, which includes `ownerData`.
|
|
161
161
|
|
|
162
|
+
**Owner write** — the proof owner may also *author* an attestation on their own item via `POST /api/v1/public/collection/:collectionId/attestations` (`attestations.publicCreate`). It is the public counterpart to the admin write, with tight guardrails:
|
|
163
|
+
|
|
164
|
+
- the caller must be authenticated and **own the linked proof** (identity — a read grant is not enough); a subject with no linked proof is rejected;
|
|
165
|
+
- they may write `value` and `ownerData` only — **`adminData` is dropped** (the business zone);
|
|
166
|
+
- `visibility` is clamped to `'public' | 'owner'` (never `'admin'`), defaulting to `'owner'`;
|
|
167
|
+
- `authorId` is forced to the caller and `metadata.authorType = 'owner'` is stamped.
|
|
168
|
+
|
|
169
|
+
**Contribute write (grant)** — the same endpoint also accepts a holder of a
|
|
170
|
+
`contribute`-scope share grant (set the token with `setGrantToken` first), so a
|
|
171
|
+
third party can add an attestation without owning the proof. Named grant →
|
|
172
|
+
attributed to the signed-in uid; public-link grant → anonymous, with `guestName`
|
|
173
|
+
for attribution; `grantId` is stamped either way. If the grant was issued with
|
|
174
|
+
`moderate: true`, the record is created with `moderationStatus: 'pending'` and is
|
|
175
|
+
held to the owner until approved.
|
|
176
|
+
|
|
177
|
+
**Moderation** — `moderationStatus` (`approved` | `pending` | `rejected`) is a gate
|
|
178
|
+
**orthogonal to `visibility`** and excluded from the hash chain. A `pending` record
|
|
179
|
+
is returned only to its author and to owner/admin audiences — never to the public,
|
|
180
|
+
whatever its target visibility — and is excluded from public analytics. The owner
|
|
181
|
+
(identity) or a collection admin resolves it with `attestations.moderate(collectionId,
|
|
182
|
+
attestationId, { decision: 'approve' | 'reject' })`; approve releases it to its
|
|
183
|
+
declared visibility, reject keeps it author+admin-only. The review queue is
|
|
184
|
+
`attestations.publicList(..., { moderationStatus: 'pending' })`. Flipping the status
|
|
185
|
+
leaves the hashed fact and its chain untouched. See
|
|
186
|
+
[Proof Share Grants → Contribute access](proof-share-grants.md#contribute-access--let-someone-add-to-a-proof).
|
|
187
|
+
|
|
188
|
+
The record joins the same append-only, hash-chained log as business/system writes. Business writes (any zone/visibility) remain admin-only.
|
|
189
|
+
|
|
162
190
|
### Visibility vs audience
|
|
163
191
|
|
|
164
192
|
`visibility` is a property of an **individual record** set at write time. `audience` describes the **caller's tier** resolved at read time. The server applies:
|
|
@@ -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
|
|
184
|
-
`enforce.visibility: "owner"` keeps
|
|
185
|
-
owner and other grant holders, not the wider
|
|
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
|