@proveanything/smartlinks 1.6.6 → 1.7.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.
@@ -0,0 +1,405 @@
1
+ // src/api/attestations.ts
2
+ import { request, post } from "../http";
3
+ // ─── Internal helper ──────────────────────────────────────────────────────────
4
+ function buildAttestationQuery(params) {
5
+ const q = new URLSearchParams();
6
+ for (const [key, value] of Object.entries(params)) {
7
+ if (value !== undefined && value !== null) {
8
+ q.append(key, String(value));
9
+ }
10
+ }
11
+ const qs = q.toString();
12
+ return qs ? `?${qs}` : '';
13
+ }
14
+ // ─── Namespace ────────────────────────────────────────────────────────────────
15
+ /**
16
+ * Postgres-backed Attestations API (v2).
17
+ *
18
+ * Attestations are an **append-only, tamper-evident fact log** that can be
19
+ * attached to any subject type in the system (`container`, `proof`, `product`,
20
+ * `tag`, etc.). Each record carries a SHA-256 `contentHash` that chains to
21
+ * the previous record for the same `(subjectType, subjectId, attestationType)`
22
+ * tuple, enabling cryptographic integrity verification.
23
+ *
24
+ * ### Admin vs Public
25
+ * - **Admin** endpoints (`/admin/collection/:id/attestations`) require a valid
26
+ * admin session or bearer token. All three data zones are returned.
27
+ * - **Public** endpoints (`/public/collection/:id/attestations`) are read-only.
28
+ * Owner elevation is available via `Authorization: Bearer <Firebase ID token>`.
29
+ *
30
+ * @see docs/attestations.md
31
+ */
32
+ export var attestations;
33
+ (function (attestations) {
34
+ // ==========================================================================
35
+ // Admin — write
36
+ // ==========================================================================
37
+ /**
38
+ * Create a single attestation (admin).
39
+ *
40
+ * @param collectionId - Collection context
41
+ * @param data - Attestation payload; `subjectType`, `subjectId`, and
42
+ * `attestationType` are required
43
+ * @returns The newly created `Attestation` record
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const a = await attestations.create('coll_123', {
48
+ * subjectType: 'container',
49
+ * subjectId: 'uuid-of-cask',
50
+ * attestationType: 'temperature',
51
+ * recordedAt: '2025-04-15T14:30:00Z',
52
+ * value: { celsius: 12.4 },
53
+ * ownerData: { sensorId: 'TEMP-7' },
54
+ * unit: '°C',
55
+ * visibility: 'public',
56
+ * })
57
+ * ```
58
+ */
59
+ async function create(collectionId, data) {
60
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/attestations`;
61
+ return post(path, data);
62
+ }
63
+ attestations.create = create;
64
+ /**
65
+ * Batch-create attestations (admin).
66
+ *
67
+ * Sends an array of `CreateAttestationInput` objects in a single request.
68
+ * The server processes them atomically and returns the created records.
69
+ *
70
+ * @param collectionId - Collection context
71
+ * @param items - Array of attestation payloads (1–1000 items recommended)
72
+ * @returns Array of created `Attestation` records, in the same order
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const records = await attestations.createBatch('coll_123', [
77
+ * { subjectType: 'container', subjectId: 'uuid1', attestationType: 'temperature', value: { celsius: 12.4 } },
78
+ * { subjectType: 'container', subjectId: 'uuid1', attestationType: 'humidity', value: { rh: 68 } },
79
+ * ])
80
+ * ```
81
+ */
82
+ async function createBatch(collectionId, items) {
83
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/attestations`;
84
+ return post(path, items);
85
+ }
86
+ attestations.createBatch = createBatch;
87
+ // ==========================================================================
88
+ // Admin — read
89
+ // ==========================================================================
90
+ /**
91
+ * List attestations for a subject (admin).
92
+ *
93
+ * Returns all three data zones. Supports filtering by type and date range.
94
+ *
95
+ * @param collectionId - Collection context
96
+ * @param params - Query parameters; `subjectType` and `subjectId` are required
97
+ * @returns `{ attestations: Attestation[] }`
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const { attestations: records } = await attestations.list('coll_123', {
102
+ * subjectType: 'container',
103
+ * subjectId: 'uuid-of-cask',
104
+ * attestationType: 'temperature',
105
+ * recordedAfter: '2025-01-01T00:00:00Z',
106
+ * limit: 50,
107
+ * })
108
+ * ```
109
+ */
110
+ async function list(collectionId, params) {
111
+ const qs = buildAttestationQuery(params);
112
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/attestations${qs}`;
113
+ return request(path);
114
+ }
115
+ attestations.list = list;
116
+ /**
117
+ * Time-series summary of attestations (admin).
118
+ *
119
+ * Aggregates attestation counts (and optionally a numeric `value` field) into
120
+ * time buckets. Useful for charting trends.
121
+ *
122
+ * @param collectionId - Collection context
123
+ * @param params - Query parameters; `subjectType`, `subjectId`, and
124
+ * `attestationType` are required
125
+ * @returns `{ summary: AttestationSummaryBucket[] }`
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const { summary } = await attestations.summary('coll_123', {
130
+ * subjectType: 'container',
131
+ * subjectId: 'uuid-of-cask',
132
+ * attestationType: 'temperature',
133
+ * valueField: 'celsius',
134
+ * groupBy: 'day',
135
+ * recordedAfter: '2025-01-01T00:00:00Z',
136
+ * })
137
+ * ```
138
+ */
139
+ async function summary(collectionId, params) {
140
+ const qs = buildAttestationQuery(params);
141
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/attestations/summary${qs}`;
142
+ return request(path);
143
+ }
144
+ attestations.summary = summary;
145
+ /**
146
+ * Latest snapshot — one record per `attestationType` (admin).
147
+ *
148
+ * Returns the most-recent attestation for each type recorded against this
149
+ * subject. Ideal for dashboards that show the current state of a container.
150
+ *
151
+ * @param collectionId - Collection context
152
+ * @param params - Query parameters; `subjectType` and `subjectId` are required
153
+ * @returns `{ latest: LatestAttestation[] }`
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const { latest } = await attestations.latest('coll_123', {
158
+ * subjectType: 'container',
159
+ * subjectId: 'uuid-of-fridge',
160
+ * })
161
+ * // latest[0].attestationType === 'temperature'
162
+ * // latest[0].latest.value === { celsius: 4.1 }
163
+ * ```
164
+ */
165
+ async function latest(collectionId, params) {
166
+ const qs = buildAttestationQuery(params);
167
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/attestations/latest${qs}`;
168
+ return request(path);
169
+ }
170
+ attestations.latest = latest;
171
+ /**
172
+ * Verify the hash chain for a `(subjectType, subjectId, attestationType)` tuple (admin).
173
+ *
174
+ * Re-computes each `contentHash` and confirms it matches the stored value
175
+ * and correctly references the previous record's hash. A `valid: false`
176
+ * result with `failedAt` indicates the first broken link.
177
+ *
178
+ * @param collectionId - Collection context
179
+ * @param params - Query parameters; all three fields are required
180
+ * @returns `ChainVerifyResult`
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const result = await attestations.verify('coll_123', {
185
+ * subjectType: 'container',
186
+ * subjectId: 'uuid-of-cask',
187
+ * attestationType: 'temperature',
188
+ * })
189
+ * if (!result.valid) {
190
+ * console.warn('Chain broken at', result.failedAt)
191
+ * }
192
+ * ```
193
+ */
194
+ async function verify(collectionId, params) {
195
+ const qs = buildAttestationQuery(params);
196
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/attestations/verify${qs}`;
197
+ return request(path);
198
+ }
199
+ attestations.verify = verify;
200
+ /**
201
+ * Tree time-series summary — aggregates across an entire container subtree (admin).
202
+ *
203
+ * Performs a BFS traversal of the container hierarchy rooted at `subjectId`,
204
+ * collects all descendant container IDs (and optionally their items), then
205
+ * aggregates attestations across all of them.
206
+ *
207
+ * @param collectionId - Collection context
208
+ * @param params - `subjectId` and `attestationType` are required;
209
+ * `subjectType` is implicitly `'container'`
210
+ * @returns `{ summary: AttestationSummaryBucket[], subjectCount: number }`
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const { summary, subjectCount } = await attestations.treeSummary('coll_123', {
215
+ * subjectId: 'root-warehouse-uuid',
216
+ * attestationType: 'temperature',
217
+ * valueField: 'celsius',
218
+ * groupBy: 'hour',
219
+ * includeItems: true,
220
+ * })
221
+ * console.log(`Aggregated over ${subjectCount} subjects`)
222
+ * ```
223
+ */
224
+ async function treeSummary(collectionId, params) {
225
+ const qs = buildAttestationQuery(Object.assign({ subjectType: 'container' }, params));
226
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/attestations/tree-summary${qs}`;
227
+ return request(path);
228
+ }
229
+ attestations.treeSummary = treeSummary;
230
+ /**
231
+ * Tree latest snapshot — most-recent record per type across a container subtree (admin).
232
+ *
233
+ * Same BFS traversal as `treeSummary`, but returns the most-recent record
234
+ * per `attestationType` aggregated across the entire subtree.
235
+ *
236
+ * @param collectionId - Collection context
237
+ * @param params - `subjectId` is required; `subjectType` is implicitly `'container'`
238
+ * @returns `{ latest: LatestAttestation[], subjectCount: number }`
239
+ */
240
+ async function treeLatest(collectionId, params) {
241
+ const qs = buildAttestationQuery(Object.assign({ subjectType: 'container' }, params));
242
+ const path = `/admin/collection/${encodeURIComponent(collectionId)}/attestations/tree-latest${qs}`;
243
+ return request(path);
244
+ }
245
+ attestations.treeLatest = treeLatest;
246
+ // ==========================================================================
247
+ // Public — read-only
248
+ // ==========================================================================
249
+ /**
250
+ * List attestations for a subject (public).
251
+ *
252
+ * Records with `visibility='admin'` are always excluded.
253
+ * Records with `visibility='owner'` are included only when the caller
254
+ * provides a valid Firebase ID token that resolves to the subject owner.
255
+ *
256
+ * The `audience` field in the response indicates the tier that was served.
257
+ *
258
+ * @param collectionId - Collection context
259
+ * @param params - Query parameters; `subjectType` and `subjectId` are required
260
+ * @returns `{ attestations: Attestation[], audience: AttestationAudience }`
261
+ *
262
+ * @example
263
+ * ```typescript
264
+ * const { attestations: records, audience } = await attestations.publicList('coll_123', {
265
+ * subjectType: 'proof',
266
+ * subjectId: 'proof-uuid',
267
+ * })
268
+ * ```
269
+ */
270
+ async function publicList(collectionId, params) {
271
+ const qs = buildAttestationQuery(params);
272
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/attestations${qs}`;
273
+ return request(path);
274
+ }
275
+ attestations.publicList = publicList;
276
+ /**
277
+ * Time-series summary (public).
278
+ *
279
+ * Always served at `audience='public'`. Same parameters as the admin version.
280
+ *
281
+ * @param collectionId - Collection context
282
+ * @param params - Query parameters; `subjectType`, `subjectId`, and
283
+ * `attestationType` are required
284
+ * @returns `{ summary: AttestationSummaryBucket[], audience: 'public' }`
285
+ */
286
+ async function publicSummary(collectionId, params) {
287
+ const qs = buildAttestationQuery(params);
288
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/attestations/summary${qs}`;
289
+ return request(path);
290
+ }
291
+ attestations.publicSummary = publicSummary;
292
+ /**
293
+ * Latest snapshot per `attestationType` (public).
294
+ *
295
+ * Owner elevation applies — provide a Firebase ID token for owner-tier data.
296
+ *
297
+ * @param collectionId - Collection context
298
+ * @param params - `subjectType` and `subjectId` are required
299
+ * @returns `{ latest: LatestAttestation[], audience: AttestationAudience }`
300
+ */
301
+ async function publicLatest(collectionId, params) {
302
+ const qs = buildAttestationQuery(params);
303
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/attestations/latest${qs}`;
304
+ return request(path);
305
+ }
306
+ attestations.publicLatest = publicLatest;
307
+ /**
308
+ * Tree time-series summary (public).
309
+ *
310
+ * Always served at `audience='public'`. Performs the same BFS traversal as
311
+ * the admin version but only includes publicly visible attestations.
312
+ *
313
+ * @param collectionId - Collection context
314
+ * @param params - `subjectId` and `attestationType` are required
315
+ * @returns `{ summary: AttestationSummaryBucket[], audience: 'public', subjectCount: number }`
316
+ */
317
+ async function publicTreeSummary(collectionId, params) {
318
+ const qs = buildAttestationQuery(Object.assign({ subjectType: 'container' }, params));
319
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/attestations/tree-summary${qs}`;
320
+ return request(path);
321
+ }
322
+ attestations.publicTreeSummary = publicTreeSummary;
323
+ /**
324
+ * Tree latest snapshot (public).
325
+ *
326
+ * @param collectionId - Collection context
327
+ * @param params - `subjectId` is required
328
+ * @returns `{ latest: LatestAttestation[], audience: 'public', subjectCount: number }`
329
+ */
330
+ async function publicTreeLatest(collectionId, params) {
331
+ const qs = buildAttestationQuery(Object.assign({ subjectType: 'container' }, params));
332
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/attestations/tree-latest${qs}`;
333
+ return request(path);
334
+ }
335
+ attestations.publicTreeLatest = publicTreeLatest;
336
+ // ==========================================================================
337
+ // Public — container-scoped shortcuts
338
+ // ==========================================================================
339
+ /**
340
+ * List attestations for a specific container (public shortcut).
341
+ *
342
+ * Equivalent to `publicList` with `subjectType='container'` and
343
+ * `subjectId=containerId` pre-filled.
344
+ *
345
+ * @param collectionId - Collection context
346
+ * @param containerId - Container UUID
347
+ * @param params - Optional filters (attestationType, date range, pagination)
348
+ */
349
+ async function publicContainerList(collectionId, containerId, params) {
350
+ const qs = buildAttestationQuery(Object.assign({}, (params !== null && params !== void 0 ? params : {})));
351
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/containers/${encodeURIComponent(containerId)}/attestations${qs}`;
352
+ return request(path);
353
+ }
354
+ attestations.publicContainerList = publicContainerList;
355
+ /**
356
+ * Time-series summary for a specific container (public shortcut).
357
+ *
358
+ * @param collectionId - Collection context
359
+ * @param containerId - Container UUID
360
+ * @param params - `attestationType` is required
361
+ */
362
+ async function publicContainerSummary(collectionId, containerId, params) {
363
+ const qs = buildAttestationQuery(Object.assign({}, (params !== null && params !== void 0 ? params : {})));
364
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/containers/${encodeURIComponent(containerId)}/attestations/summary${qs}`;
365
+ return request(path);
366
+ }
367
+ attestations.publicContainerSummary = publicContainerSummary;
368
+ /**
369
+ * Latest snapshot for a specific container (public shortcut).
370
+ *
371
+ * @param collectionId - Collection context
372
+ * @param containerId - Container UUID
373
+ */
374
+ async function publicContainerLatest(collectionId, containerId) {
375
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/containers/${encodeURIComponent(containerId)}/attestations/latest`;
376
+ return request(path);
377
+ }
378
+ attestations.publicContainerLatest = publicContainerLatest;
379
+ /**
380
+ * Tree time-series summary rooted at a specific container (public shortcut).
381
+ *
382
+ * @param collectionId - Collection context
383
+ * @param containerId - Root container UUID
384
+ * @param params - `attestationType` is required
385
+ */
386
+ async function publicContainerTreeSummary(collectionId, containerId, params) {
387
+ const qs = buildAttestationQuery(Object.assign({}, (params !== null && params !== void 0 ? params : {})));
388
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/containers/${encodeURIComponent(containerId)}/attestations/tree-summary${qs}`;
389
+ return request(path);
390
+ }
391
+ attestations.publicContainerTreeSummary = publicContainerTreeSummary;
392
+ /**
393
+ * Tree latest snapshot rooted at a specific container (public shortcut).
394
+ *
395
+ * @param collectionId - Collection context
396
+ * @param containerId - Root container UUID
397
+ * @param params - Optional `includeItems` flag
398
+ */
399
+ async function publicContainerTreeLatest(collectionId, containerId, params) {
400
+ const qs = buildAttestationQuery(Object.assign({}, (params !== null && params !== void 0 ? params : {})));
401
+ const path = `/public/collection/${encodeURIComponent(collectionId)}/containers/${encodeURIComponent(containerId)}/attestations/tree-latest${qs}`;
402
+ return request(path);
403
+ }
404
+ attestations.publicContainerTreeLatest = publicContainerTreeLatest;
405
+ })(attestations || (attestations = {}));
@@ -0,0 +1,236 @@
1
+ import type { Container, CreateContainerInput, UpdateContainerInput, AddContainerItemsInput, RemoveContainerItemsInput, ListContainersParams, ListContainersResponse, PublicListContainersResponse, GetContainerParams, ListContainerItemsParams, ContainerItemsResponse, AddContainerItemsResponse, RemoveContainerItemsResponse, FindContainersForItemParams, FindContainersForItemResponse } from "../types/containers";
2
+ /**
3
+ * Container Tracking API.
4
+ *
5
+ * Containers are physical or logical groupings (pallets, fridges, casks,
6
+ * shipping containers, warehouses, etc.) that support **hierarchical nesting**
7
+ * via `parentContainerId`. Each container can hold items of type `tag`,
8
+ * `proof`, `serial`, `order_item`, or even other `container`s.
9
+ *
10
+ * ### Admin vs Public
11
+ * - **Admin** routes (`/admin/collection/:id/containers`) allow full CRUD and
12
+ * mutation of item membership.
13
+ * - **Public** routes (`/public/collection/:id/containers`) are read-only.
14
+ * Soft-deleted containers and containers with `metadata.publicListing === false`
15
+ * are excluded from list results.
16
+ *
17
+ * Attestations against containers are managed through the `attestations`
18
+ * namespace. Container-scoped public shortcuts are available via
19
+ * `attestations.publicContainer*` helpers.
20
+ *
21
+ * @see docs/container-tracking.md
22
+ */
23
+ export declare namespace containers {
24
+ /**
25
+ * Create a new container (admin).
26
+ *
27
+ * @param collectionId - Collection context
28
+ * @param data - Container definition; `containerType` is required
29
+ * @returns The created `Container` record
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const cask = await containers.create('coll_123', {
34
+ * containerType: 'cask',
35
+ * ref: 'CASK-0042',
36
+ * name: 'Cask 42 — Single Malt',
37
+ * metadata: { distilleryYear: 2019, capacity: 200 },
38
+ * })
39
+ * ```
40
+ */
41
+ function create(collectionId: string, data: CreateContainerInput): Promise<Container>;
42
+ /**
43
+ * List containers (admin).
44
+ *
45
+ * Supports filtering by type, status, ref, parent, and top-level flag.
46
+ *
47
+ * @param collectionId - Collection context
48
+ * @param params - Optional filter and pagination parameters
49
+ * @returns `{ containers: Container[], limit: number, offset: number }`
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * // All active pallets
54
+ * const { containers: pallets } = await containers.list('coll_123', {
55
+ * containerType: 'pallet',
56
+ * status: 'active',
57
+ * limit: 50,
58
+ * })
59
+ *
60
+ * // Top-level containers only
61
+ * const { containers: roots } = await containers.list('coll_123', { topLevel: true })
62
+ * ```
63
+ */
64
+ function list(collectionId: string, params?: ListContainersParams): Promise<ListContainersResponse>;
65
+ /**
66
+ * Reverse lookup — find all containers currently holding a specific item (admin).
67
+ *
68
+ * @param collectionId - Collection context
69
+ * @param params - `itemType` and `itemId` are required
70
+ * @returns `{ containers: Container[] }`
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const { containers: holding } = await containers.findForItem('coll_123', {
75
+ * itemType: 'proof',
76
+ * itemId: 'proof-uuid',
77
+ * })
78
+ * ```
79
+ */
80
+ function findForItem(collectionId: string, params: FindContainersForItemParams): Promise<FindContainersForItemResponse>;
81
+ /**
82
+ * Get a single container by ID (admin).
83
+ *
84
+ * Pass `?tree=true` to recursively embed children, and/or
85
+ * `?includeContents=true` to embed the current item list.
86
+ *
87
+ * @param collectionId - Collection context
88
+ * @param containerId - Container UUID
89
+ * @param params - Optional display options
90
+ * @returns `Container` (with optional `children` and `items` arrays)
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * // Flat
95
+ * const cask = await containers.get('coll_123', 'cask-uuid')
96
+ *
97
+ * // Full tree with contents
98
+ * const tree = await containers.get('coll_123', 'warehouse-uuid', {
99
+ * tree: true,
100
+ * treeDepth: 3,
101
+ * includeContents: true,
102
+ * })
103
+ * ```
104
+ */
105
+ function get(collectionId: string, containerId: string, params?: GetContainerParams): Promise<Container>;
106
+ /**
107
+ * Partially update a container (admin).
108
+ *
109
+ * Only fields present in the request body are modified.
110
+ * Pass `parentContainerId: null` to promote a container to top-level.
111
+ *
112
+ * @param collectionId - Collection context
113
+ * @param containerId - Container UUID
114
+ * @param data - Fields to update
115
+ * @returns Updated `Container`
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const updated = await containers.update('coll_123', 'cask-uuid', {
120
+ * status: 'archived',
121
+ * metadata: { bottledAt: '2025-04-01' },
122
+ * })
123
+ * ```
124
+ */
125
+ function update(collectionId: string, containerId: string, data: UpdateContainerInput): Promise<Container>;
126
+ /**
127
+ * Soft-delete a container (admin).
128
+ *
129
+ * Sets `deletedAt`; the record and its full item history remain queryable
130
+ * by admins. Public API responses automatically exclude deleted containers.
131
+ *
132
+ * @param collectionId - Collection context
133
+ * @param containerId - Container UUID
134
+ * @returns `{ success: true }`
135
+ */
136
+ function remove(collectionId: string, containerId: string): Promise<{
137
+ success: true;
138
+ }>;
139
+ /**
140
+ * List items currently (or historically) inside a container (admin).
141
+ *
142
+ * Pass `history: true` to include removed items and see the full membership log.
143
+ *
144
+ * @param collectionId - Collection context
145
+ * @param containerId - Container UUID
146
+ * @param params - Optional filters and pagination
147
+ * @returns `{ items: ContainerItem[], limit: number, offset: number }`
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * // Current contents
152
+ * const { items } = await containers.listItems('coll_123', 'cask-uuid')
153
+ *
154
+ * // Full history including removed items
155
+ * const { items: history } = await containers.listItems('coll_123', 'cask-uuid', { history: true })
156
+ * ```
157
+ */
158
+ function listItems(collectionId: string, containerId: string, params?: ListContainerItemsParams): Promise<ContainerItemsResponse>;
159
+ /**
160
+ * Add one or more items to a container (admin).
161
+ *
162
+ * Each item requires `itemType` and `itemId`. Pass `productId` / `proofId`
163
+ * for denormalisation convenience.
164
+ *
165
+ * @param collectionId - Collection context
166
+ * @param containerId - Container UUID
167
+ * @param data - Items to add
168
+ * @returns `{ items: ContainerItem[] }` — the newly created membership records
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * const { items } = await containers.addItems('coll_123', 'pallet-uuid', {
173
+ * items: [
174
+ * { itemType: 'tag', itemId: 'NFC-00AABBCC' },
175
+ * { itemType: 'proof', itemId: 'proof-uuid', productId: 'product-id' },
176
+ * ],
177
+ * })
178
+ * ```
179
+ */
180
+ function addItems(collectionId: string, containerId: string, data: AddContainerItemsInput): Promise<AddContainerItemsResponse>;
181
+ /**
182
+ * Soft-remove items from a container (admin).
183
+ *
184
+ * Sets `removedAt` on the specified `ContainerItem` records. The records
185
+ * are retained in the history log and can be queried with `history: true`.
186
+ *
187
+ * @param collectionId - Collection context
188
+ * @param containerId - Container UUID
189
+ * @param data - `ids` array of `ContainerItem` UUIDs to remove
190
+ * @returns `{ success: true, removedCount: number }`
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * const result = await containers.removeItems('coll_123', 'pallet-uuid', {
195
+ * ids: ['container-item-uuid-1', 'container-item-uuid-2'],
196
+ * })
197
+ * console.log(`Removed ${result.removedCount} items`)
198
+ * ```
199
+ */
200
+ function removeItems(collectionId: string, containerId: string, data: RemoveContainerItemsInput): Promise<RemoveContainerItemsResponse>;
201
+ /**
202
+ * List containers (public).
203
+ *
204
+ * Soft-deleted containers and containers with `metadata.publicListing === false`
205
+ * are excluded from results.
206
+ *
207
+ * @param collectionId - Collection context
208
+ * @param params - Optional filter and pagination parameters
209
+ * @returns `{ containers: Container[] }`
210
+ */
211
+ function publicList(collectionId: string, params?: ListContainersParams): Promise<PublicListContainersResponse>;
212
+ /**
213
+ * Get a single container (public).
214
+ *
215
+ * Soft-deleted containers return a 404. Same `?tree` and
216
+ * `?includeContents` options as the admin version.
217
+ *
218
+ * @param collectionId - Collection context
219
+ * @param containerId - Container UUID
220
+ * @param params - Optional display options
221
+ * @returns `Container`
222
+ */
223
+ function publicGet(collectionId: string, containerId: string, params?: GetContainerParams): Promise<Container>;
224
+ /**
225
+ * List current contents of a container (public).
226
+ *
227
+ * Returns only items where `removedAt` is null. No `?history` option on
228
+ * the public side.
229
+ *
230
+ * @param collectionId - Collection context
231
+ * @param containerId - Container UUID
232
+ * @param params - Optional pagination
233
+ * @returns `{ items: ContainerItem[], limit: number, offset: number }`
234
+ */
235
+ function publicListItems(collectionId: string, containerId: string, params?: Pick<ListContainerItemsParams, 'limit' | 'offset'>): Promise<ContainerItemsResponse>;
236
+ }