@alvera-ai/platform-sdk 0.18.2 → 0.19.2-next.g845dfdf
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/.agent/ai_sandbox.md +3 -3
- package/.agent/cookbook/_fixtures/payments-compliance/_compliance_screenings_generic_table.liquid +1 -1
- package/.agent/cookbook/_fixtures/payments-compliance/_payment_accounts_generic_table.liquid +1 -1
- package/.agent/cookbook/organic-marketing.md +207 -11
- package/.agent/cookbook/payments-compliance.md +7 -7
- package/.agent/cookbook/primary-care.md +22 -8
- package/.agent/cookbook/subscription-saas.md +14 -13
- package/.agent/data_activation_clients.md +177 -11
- package/.agent/datalakes.md +1 -1
- package/.agent/interoperability_contracts.md +1 -1
- package/.agent/mdm.md +56 -1
- package/.agent/mock-services.md +4 -4
- package/.agent/workflows.md +68 -1
- package/dist/index.d.mts +118 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +56 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -164,6 +164,70 @@ Anchor on the empty-render-passes rule, not on the Liquid
|
|
|
164
164
|
keyword — `{% if ... %}...{% endif %}` and
|
|
165
165
|
`{% unless ... %}...{% endunless %}` are equivalent.
|
|
166
166
|
|
|
167
|
+
### `rows_from_file_template` says HOW MANY rows, never what is in them
|
|
168
|
+
|
|
169
|
+
A fetch lands a file in storage. `rows_from_file_template` is a
|
|
170
|
+
Liquid template that turns that file into the list of rows to
|
|
171
|
+
ingest. It may be set on **any** file — the content type decides
|
|
172
|
+
only how the file is DECODED, never whether a template is
|
|
173
|
+
allowed — and a run is never refused for declaring one.
|
|
174
|
+
|
|
175
|
+
`msg` binds to the decoded **whole file**: one value per file,
|
|
176
|
+
never a row. What it holds depends on how the fetch stored the
|
|
177
|
+
file:
|
|
178
|
+
|
|
179
|
+
| stored as | `msg` is |
|
|
180
|
+
|------------------------|-------------------------------------------|
|
|
181
|
+
| `application/json` | the parsed document |
|
|
182
|
+
| `application/x-ndjson` | the list of every parsed line |
|
|
183
|
+
| `text/csv` | the list of row maps, keyed by header |
|
|
184
|
+
| PDF, PNG, JPEG, WebP | `{ r2_key, content_type }` — a pointer, bytes undecoded |
|
|
185
|
+
|
|
186
|
+
The template must render a **JSON array**. Liquid renders text,
|
|
187
|
+
so any value has to be serialised on the way out; `to_json` is
|
|
188
|
+
the filter that does it, and there is no inverse — nothing parses
|
|
189
|
+
a JSON string back into a value inside the template.
|
|
190
|
+
|
|
191
|
+
Three shapes cover nearly everything:
|
|
192
|
+
|
|
193
|
+
- **one document becomes many rows** —
|
|
194
|
+
`{{ msg.data | to_json }}`
|
|
195
|
+
- **many rows become fewer** —
|
|
196
|
+
`{% assign kept = msg | where: "status", "active" %}{{ kept | to_json }}`
|
|
197
|
+
- **a whole file becomes one row** — `[{{ msg | to_json }}]`.
|
|
198
|
+
The brackets are what make it a list; this is the usual shape
|
|
199
|
+
for a PDF or an image, where `msg` is already the pointer the
|
|
200
|
+
contract needs.
|
|
201
|
+
|
|
202
|
+
**Leave it unset when the file is already the rows.** A
|
|
203
|
+
`sql_query` export, a CSV, and most `sftp` / `s3` bodies land as
|
|
204
|
+
rows already. Unset means take them as they are — the common
|
|
205
|
+
case, and it streams a chunk at a time instead of holding the
|
|
206
|
+
file in memory, which a template cannot do because it has to see
|
|
207
|
+
the whole file at once.
|
|
208
|
+
|
|
209
|
+
**The template decides how many rows there are; the contract
|
|
210
|
+
decides what is in each one.** A contract runs per row and can
|
|
211
|
+
never change the count, which is the one thing only this
|
|
212
|
+
template can do. Renaming or reshaping fields belongs in the
|
|
213
|
+
contract (`interoperability_contracts.md`), not here.
|
|
214
|
+
|
|
215
|
+
It runs on `.runManually`, on `.ingestFile`, and on every cron
|
|
216
|
+
fire — every path that fetches a file. It does **not** run on
|
|
217
|
+
`.ingest`, which takes rows inline and has no file to decode.
|
|
218
|
+
|
|
219
|
+
Extraction happens in a background job, so a template that fails
|
|
220
|
+
never reaches the HTTP response — `.runManually` still returns
|
|
221
|
+
its `batch_id`. The failure surfaces as a `data_activation_logs`
|
|
222
|
+
row you read back through `.logs.list` (§6.4), and in the
|
|
223
|
+
platform's error log under `error_code: rows_template_failed`.
|
|
224
|
+
|
|
225
|
+
**Renamed.** This field was `response_extractor` until
|
|
226
|
+
2026-09-14; manifests and contracts written against the old name
|
|
227
|
+
need updating. The tool-level `response_extractor` (`tools.md`)
|
|
228
|
+
is a different field doing a different job — it maps a model
|
|
229
|
+
provider's envelope into a canonical result — and keeps its name.
|
|
230
|
+
|
|
167
231
|
## 3. Field ownership
|
|
168
232
|
|
|
169
233
|
**Server-derived (Response-only).** Universal set from
|
|
@@ -199,18 +263,17 @@ downstream_connection_ids optional UUID[] — DACs triggered after this
|
|
|
199
263
|
filter_config optional embed — TemplateConfig; server-pinned
|
|
200
264
|
output_schema (enum ["true","false"]). A row-
|
|
201
265
|
level filter evaluated per fetched row
|
|
202
|
-
|
|
203
|
-
a Liquid template that
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
`
|
|
207
|
-
`cookbook/subscription-saas.md` §032–035
|
|
266
|
+
rows_from_file_template optional embed — TemplateConfig ({ type, body });
|
|
267
|
+
a Liquid template that says where the rows are
|
|
268
|
+
inside a fetched file. It may be set on ANY
|
|
269
|
+
file and is never refused — see §2 for what
|
|
270
|
+
`msg` binds to and when to leave it unset
|
|
208
271
|
```
|
|
209
272
|
|
|
210
273
|
**Write-only (Request-only).** None — every caller-supplied
|
|
211
274
|
field round-trips on the response (the virtual array
|
|
212
275
|
round-trips under `interoperability_contracts` on response).
|
|
213
|
-
`filter_config` / `
|
|
276
|
+
`filter_config` / `rows_from_file_template` come back under the read-only
|
|
214
277
|
`SimpleTemplateConfigResponse` shape (their `output_schema` is
|
|
215
278
|
server-pinned and not echoed).
|
|
216
279
|
|
|
@@ -314,7 +377,7 @@ Three run shapes exist, selected by the bound tool's
|
|
|
314
377
|
All three produce **log rows** observable through
|
|
315
378
|
`api.dataActivationClients.logs.*` (§6.4), and the canonical way
|
|
316
379
|
to **verify** that ingestion worked is the two-step
|
|
317
|
-
dataset-search pattern in §6.
|
|
380
|
+
dataset-search pattern in §6.6.
|
|
318
381
|
|
|
319
382
|
### 6.1 Inline JSON ingestion — `.ingest`
|
|
320
383
|
|
|
@@ -334,7 +397,7 @@ const { data } = await api.dataActivationClients.ingest(
|
|
|
334
397
|
The response returns **immediately after enqueueing**, not
|
|
335
398
|
after ingestion completes. To know when the row has actually
|
|
336
399
|
been written, poll the logs (§6.4) or use the verification
|
|
337
|
-
pattern (§6.
|
|
400
|
+
pattern (§6.6).
|
|
338
401
|
|
|
339
402
|
The `batch_id` is the most important field on the response —
|
|
340
403
|
every downstream log row and dataset row carries the same
|
|
@@ -471,7 +534,110 @@ merge step has committed the ndjson archive. Use
|
|
|
471
534
|
`output_files.length > 0` as the "this batch's rows are fully
|
|
472
535
|
durable" signal — not just the presence of the log row.
|
|
473
536
|
|
|
474
|
-
### 6.5
|
|
537
|
+
### 6.5 Runs subresource — `.batches.list` / `.batches.get`
|
|
538
|
+
|
|
539
|
+
A **run** is one record; the log rows of §6.4 are one record per
|
|
540
|
+
dataset table that run wrote into. Read the run to answer *"is this
|
|
541
|
+
over, and how did it end"*; read the logs for the per-table detail,
|
|
542
|
+
filtered on the same `batch_id`.
|
|
543
|
+
|
|
544
|
+
Before this record existed, the only way to ask whether a run had
|
|
545
|
+
finished was to count log rows and guess — which cannot tell a run
|
|
546
|
+
still going from one that produced nothing and never will. A run
|
|
547
|
+
that was skipped or that died looked exactly like a slow one until
|
|
548
|
+
the caller's timeout expired.
|
|
549
|
+
|
|
550
|
+
```
|
|
551
|
+
batch_id UUID — the run identifier, the same one `.ingest`,
|
|
552
|
+
`.ingestFile` and `.runManually` hand back, and the
|
|
553
|
+
one stamped on every per-table log row of this run
|
|
554
|
+
client_id UUID — the owning activation client
|
|
555
|
+
closed_at ISO timestamp | null — when the run was attempted and
|
|
556
|
+
exhausted. Null while it is still going. It does NOT
|
|
557
|
+
mean rows landed and it does NOT mean the archive was
|
|
558
|
+
merged — read `status` for the outcome, and only once
|
|
559
|
+
this is set.
|
|
560
|
+
status 'processing' | 'succeeded' | 'partial' | 'skipped' | 'failed'
|
|
561
|
+
rows_total number — source rows enqueued for this run. The run's own
|
|
562
|
+
count; each per-table log keeps its own.
|
|
563
|
+
inserted_at ISO timestamp — when the run started
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**`status` means nothing until `closed_at` is set.** A run in flight
|
|
567
|
+
always reads `processing`. Once it is closed:
|
|
568
|
+
|
|
569
|
+
| status | what happened |
|
|
570
|
+
|---|---|
|
|
571
|
+
| `succeeded` | it ran and nothing was refused |
|
|
572
|
+
| `partial` | it ran and at least one row was refused on the way in; the rows that landed are still there |
|
|
573
|
+
| `skipped` | it ran and there was nothing to do — empty file, every row filtered out, or the client has no contracts |
|
|
574
|
+
| `failed` | it died before writing anything |
|
|
575
|
+
|
|
576
|
+
```typescript
|
|
577
|
+
// Paginated list of runs for an activation client. Takes the full Flop
|
|
578
|
+
// query (page / page_size / order_by / order_directions / filters —
|
|
579
|
+
// type_naming.md); without it, page 1 only.
|
|
580
|
+
const { data } = await api.dataActivationClients.batches.list(
|
|
581
|
+
tenantSlug, datalakeSlug, activationClientSlug,
|
|
582
|
+
{ page: 1, page_size: 50, order_by: ['inserted_at'], order_directions: ['desc'] },
|
|
583
|
+
)
|
|
584
|
+
// data.data — array of run records; data.meta — pagination
|
|
585
|
+
|
|
586
|
+
// Fetch one run by its batch_id.
|
|
587
|
+
const { data: run } = await api.dataActivationClients.batches.get(
|
|
588
|
+
tenantSlug, datalakeSlug, activationClientSlug, batchId,
|
|
589
|
+
)
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
> **The fourth argument is the `batch_id`, not the record's `id`.**
|
|
593
|
+
> A run record carries both, and both are UUIDs. The route looks the
|
|
594
|
+
> run up by its `batch_id` — the identifier the ingest handed you — so
|
|
595
|
+
> passing the record's own `id` is a **404**, not a type error.
|
|
596
|
+
|
|
597
|
+
#### Waiting on a run
|
|
598
|
+
|
|
599
|
+
This is what the run record is for. Poll until `closed_at` is set,
|
|
600
|
+
then branch on `status` — never poll `status` alone, because a run
|
|
601
|
+
in flight reads `processing` forever and tells you nothing:
|
|
602
|
+
|
|
603
|
+
```typescript
|
|
604
|
+
const { data: ingest } = await api.dataActivationClients.ingest(
|
|
605
|
+
tenantSlug, datalakeSlug, activationClientSlug, { data: row },
|
|
606
|
+
)
|
|
607
|
+
|
|
608
|
+
const deadline = Date.now() + 120_000
|
|
609
|
+
let run
|
|
610
|
+
for (;;) {
|
|
611
|
+
const { data } = await api.dataActivationClients.batches.get(
|
|
612
|
+
tenantSlug, datalakeSlug, activationClientSlug, ingest.batch_id,
|
|
613
|
+
)
|
|
614
|
+
if (data.closed_at != null) { run = data; break }
|
|
615
|
+
if (Date.now() > deadline) throw new Error(`run ${ingest.batch_id} never closed`)
|
|
616
|
+
await new Promise((r) => setTimeout(r, 1_000))
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (run.status === 'failed') {
|
|
620
|
+
throw new Error(`run ${ingest.batch_id} failed before writing anything`)
|
|
621
|
+
}
|
|
622
|
+
if (run.status === 'skipped') {
|
|
623
|
+
throw new Error(`run ${ingest.batch_id} had nothing to do — check the row filter and the client's contracts`)
|
|
624
|
+
}
|
|
625
|
+
// 'succeeded' or 'partial' — the run is over and rows were written.
|
|
626
|
+
// For a partial, read the log rows (§6.4) for which table refused what.
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
A run that failed or was skipped **ends the wait immediately, carrying
|
|
630
|
+
why**. That is the whole difference from counting rows: a blind poll
|
|
631
|
+
spends its full timeout and then reports nothing about the cause.
|
|
632
|
+
|
|
633
|
+
> **`closed_at` is not the same as "my row is queryable".** It says the
|
|
634
|
+
> run is over. It does not say the archive was merged (that is
|
|
635
|
+
> `output_files` on the log rows, §6.4), and for one specific row it
|
|
636
|
+
> does not replace the landing check in §6.6 — it makes that check a
|
|
637
|
+
> single read after the run is known finished, instead of a guess
|
|
638
|
+
> against a deadline.
|
|
639
|
+
|
|
640
|
+
### 6.6 Verifying ingestion: the two-step dataset search
|
|
475
641
|
|
|
476
642
|
> **Simplest landing check — `executeSql`.** Ingestion is async (the row
|
|
477
643
|
> commits a moment after the `202`). When you just need to know a row
|
|
@@ -638,7 +804,7 @@ screen. Pick the mode by which of those two readers you are serving.
|
|
|
638
804
|
response carries `batch_id` + `jobs_count`, signalling that
|
|
639
805
|
downstream jobs have been enqueued — not that they've
|
|
640
806
|
completed. Poll logs (or use the search verification
|
|
641
|
-
pattern in §6.
|
|
807
|
+
pattern in §6.6) before treating the row as ingested.
|
|
642
808
|
|
|
643
809
|
7. **`dataset_updated > 0` is the load-bearing freshness
|
|
644
810
|
gate.** `rows_ingested` flips as soon as the per-row job
|
package/.agent/datalakes.md
CHANGED
|
@@ -110,7 +110,7 @@ The platform does NOT expose a query API over the archive itself —
|
|
|
110
110
|
cold reads happen externally so the platform's processes aren't
|
|
111
111
|
responsible for analytical workloads. Live data lives in the
|
|
112
112
|
datalake's Postgres halves (queryable via the dataset search
|
|
113
|
-
two-step pattern in `data_activation_clients.md` §6.
|
|
113
|
+
two-step pattern in `data_activation_clients.md` §6.6); historical
|
|
114
114
|
data lives in the cloud-storage buckets configured here.
|
|
115
115
|
|
|
116
116
|
### Canonical create body
|
|
@@ -299,7 +299,7 @@ in the datalake and there is nothing to search afterwards. The
|
|
|
299
299
|
contract's `resource_type` destination) runs only when the DAC
|
|
300
300
|
worker ingests a row — i.e. on `dataActivationClients.ingest`, not
|
|
301
301
|
on `.run`. To prove a row *landed*, ingest and then query by
|
|
302
|
-
`batch_id` (see `data_activation_clients.md` §6.
|
|
302
|
+
`batch_id` (see `data_activation_clients.md` §6.6).
|
|
303
303
|
|
|
304
304
|
```typescript
|
|
305
305
|
const { data: result } = await api.interoperabilityContracts.run(
|
package/.agent/mdm.md
CHANGED
|
@@ -185,6 +185,61 @@ is a 404, not a `'not_verified'`. The distinction matters:
|
|
|
185
185
|
A consumer that conflates the two will mis-route an identity
|
|
186
186
|
challenge as a missing-record error.
|
|
187
187
|
|
|
188
|
+
### One label per kind of identifier a subject holds
|
|
189
|
+
|
|
190
|
+
An identification attaches to a legal entity under a label — its `uri` —
|
|
191
|
+
alongside an `id_type`. The pair `(uri, id_type)` is a **slot** on that
|
|
192
|
+
subject, and a subject holds each slot once. Two identifications under the
|
|
193
|
+
same pair are refused, not merged and not resolved to a winner.
|
|
194
|
+
|
|
195
|
+
So a subject that carries more than one identifier needs a label per kind.
|
|
196
|
+
Jane, from a Shopify store, with an email and a phone:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
"identifications": [
|
|
200
|
+
{ "id_type": "digital_identifier",
|
|
201
|
+
"uri": "shopify",
|
|
202
|
+
"id_number": "jane@example.com" },
|
|
203
|
+
{ "id_type": "digital_identifier",
|
|
204
|
+
"uri": "shopify::phone",
|
|
205
|
+
"id_number": "+15551234" }
|
|
206
|
+
]
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Written with `"uri": "shopify"` on both, the second is refused — the database
|
|
210
|
+
enforces it as `legal_entity_identifications_entity_uri_type_uk`.
|
|
211
|
+
|
|
212
|
+
The convention: the bare source identifies the **subject**; anything else the
|
|
213
|
+
subject carries gets its own label beneath it.
|
|
214
|
+
|
|
215
|
+
**Do not re-label identifications that already exist.** Changing the `uri` on a
|
|
216
|
+
recipe that has already run sends the next ingest to a DIFFERENT slot, which
|
|
217
|
+
adds a second identification rather than updating the first — the original is
|
|
218
|
+
orphaned, silently, and both then answer to the same person.
|
|
219
|
+
|
|
220
|
+
### What a resolve does to the slots it does not name
|
|
221
|
+
|
|
222
|
+
A resolve speaks only about the slots it names:
|
|
223
|
+
|
|
224
|
+
| the slot you send | what happens |
|
|
225
|
+
|---|---|
|
|
226
|
+
| named, already filled | **overwritten** |
|
|
227
|
+
| named, empty | **added** |
|
|
228
|
+
| **not mentioned** | **kept, untouched** |
|
|
229
|
+
|
|
230
|
+
The third row is the one worth designing around, and the one nothing else
|
|
231
|
+
states. Several lanes can each resolve the same subject knowing only their own
|
|
232
|
+
identifiers, without destroying each other's work: a marketing lane sending
|
|
233
|
+
only an email and a billing lane sending only a phone both survive, in either
|
|
234
|
+
order.
|
|
235
|
+
|
|
236
|
+
Two limits that follow from the same rule:
|
|
237
|
+
|
|
238
|
+
- **A slot cannot be emptied through a resolve.** Omitting it means "leave it";
|
|
239
|
+
there is no value that means "remove it".
|
|
240
|
+
- **Two values under one `(uri, id_type)` in a single payload are refused**
|
|
241
|
+
rather than resolved to a winner — the platform does not pick.
|
|
242
|
+
|
|
188
243
|
## 3. Field ownership
|
|
189
244
|
|
|
190
245
|
**Server-derived (Response-only).**
|
|
@@ -284,7 +339,7 @@ SDK surface:
|
|
|
284
339
|
|
|
285
340
|
Today there is no `.list`, `.get`, or `.metadata` on the MDM
|
|
286
341
|
namespace — subjects themselves are queried through the dataset
|
|
287
|
-
search surface (see `data_activation_clients.md` §6.
|
|
342
|
+
search surface (see `data_activation_clients.md` §6.6), not
|
|
288
343
|
through `api.mdm`.
|
|
289
344
|
|
|
290
345
|
## 6. Gotchas
|
package/.agent/mock-services.md
CHANGED
|
@@ -95,21 +95,21 @@ flowchart TD
|
|
|
95
95
|
end
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
**It lives in this repo**, at `cloudflare
|
|
98
|
+
**It lives in this repo**, at `cloudflare/workers/mock/`. Deploy from a normal checkout:
|
|
99
99
|
|
|
100
100
|
```bash
|
|
101
|
-
cd cloudflare
|
|
101
|
+
cd cloudflare/workers/mock && wrangler deploy
|
|
102
102
|
```
|
|
103
103
|
|
|
104
104
|
The single line that makes this work without a vendored copy of the corpus:
|
|
105
105
|
|
|
106
106
|
```jsonc
|
|
107
|
-
"image_build_context": "
|
|
107
|
+
"image_build_context": "../../.."
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
That sets the Docker build context to the repo root, so the Dockerfile copies
|
|
111
111
|
`wm_mappings/` and `wm_response_files/` from where they already live. Without it
|
|
112
|
-
the context is `cloudflare
|
|
112
|
+
the context is `cloudflare/workers/mock/` and the corpus would have to be duplicated there —
|
|
113
113
|
two directories that look identical until they quietly aren't.
|
|
114
114
|
|
|
115
115
|
### There is no authentication
|
package/.agent/workflows.md
CHANGED
|
@@ -492,6 +492,73 @@ actions required array — inline; replace-on-PUT
|
|
|
492
492
|
workflow_ai_agents optional array — inline; replace-on-PUT (see §3)
|
|
493
493
|
```
|
|
494
494
|
|
|
495
|
+
Caller-supplied fields **inside each `context_datasets[*]`** row:
|
|
496
|
+
|
|
497
|
+
```
|
|
498
|
+
dataset_type required string — CLOSED ENUM, not free text. An
|
|
499
|
+
arbitrary value 422s at apply and
|
|
500
|
+
the error enumerates the allowed
|
|
501
|
+
types
|
|
502
|
+
generic_table_id required UUID when dataset_type == 'generic_table';
|
|
503
|
+
omit otherwise. NOT the same field
|
|
504
|
+
as the workflow's own
|
|
505
|
+
`generic_table_id` one level up
|
|
506
|
+
where_clause optional string — Liquid, max 10_000 chars (see
|
|
507
|
+
below for what it can reach, and
|
|
508
|
+
which tier it runs against)
|
|
509
|
+
limit optional int — must be positive
|
|
510
|
+
position optional int — default 0
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Reading what a context query returned
|
|
514
|
+
|
|
515
|
+
`additional_context.<dataset_type>` — the `dataset_type` string **literally**,
|
|
516
|
+
not the table name and not a slug. A `document` context is read at
|
|
517
|
+
`additional_context.document`.
|
|
518
|
+
|
|
519
|
+
Do not confuse this with the AI-agent form documented above
|
|
520
|
+
(`additional_context.<agent_slug>.<field>`): an agent is keyed by its slug, a
|
|
521
|
+
context dataset by its type.
|
|
522
|
+
|
|
523
|
+
### ⚠ Two context datasets of the same `dataset_type` silently overwrite
|
|
524
|
+
|
|
525
|
+
The loader accumulates them into a map keyed by `dataset_type`, so declaring
|
|
526
|
+
two of the same type leaves **only the last one**. There is no error and no
|
|
527
|
+
warning — the workflow runs happily against the wrong context. If you need two
|
|
528
|
+
slices of one type, express it as one query with a wider `where_clause`.
|
|
529
|
+
|
|
530
|
+
### The `where_clause` reaches the row differently than the filter does
|
|
531
|
+
|
|
532
|
+
This asymmetry is the easiest thing here to get wrong:
|
|
533
|
+
|
|
534
|
+
```
|
|
535
|
+
where clause {{ <dataset_type>.field }} e.g. {{ generic_table.external_client_id }}
|
|
536
|
+
filter {{ event_dataset.field }} the SAME row, different accessor
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
That makes three conventions for "the current row" across this corpus — the
|
|
540
|
+
third being `msg.row.x` in an interoperability filter versus `msg.x` in its
|
|
541
|
+
transform. Nothing about a name tells you which one you are in; the surface you
|
|
542
|
+
are authoring does.
|
|
543
|
+
|
|
544
|
+
### Context queries run against the REGULATED tier
|
|
545
|
+
|
|
546
|
+
The loader reads context in regulated mode, so a `where_clause` must name the
|
|
547
|
+
**regulated** table alias (e.g. `regulated_alvera_custom_unsubscribe_list`),
|
|
548
|
+
not the unregulated name. This changes every where clause you write, and a
|
|
549
|
+
clause written against the unregulated name finds nothing rather than failing
|
|
550
|
+
loudly.
|
|
551
|
+
|
|
552
|
+
### `context_datasets` cannot be cleared by omission
|
|
553
|
+
|
|
554
|
+
It is a **required, replace-on-PUT array**. Dropping the block from a manifest
|
|
555
|
+
does not clear it: the server retains what was last deployed, the rendered and
|
|
556
|
+
deployed checksums never converge, and every subsequent `plan` reports drift on
|
|
557
|
+
a config that was just applied. Send an explicit `[]` to mean "no context".
|
|
558
|
+
|
|
559
|
+
Same class as the `assume_role_external_id` convergence note — an omission that
|
|
560
|
+
reads as "leave it alone" on the wire and as "remove it" in the author's head.
|
|
561
|
+
|
|
495
562
|
Caller-supplied fields **inside each `actions[*]`** row:
|
|
496
563
|
|
|
497
564
|
```
|
|
@@ -647,7 +714,7 @@ an error to retry.
|
|
|
647
714
|
tables. For a **platform dataset** the server assigns the alias
|
|
648
715
|
(`le` legal entities, `m` messages, `al` action logs, `d` documents,
|
|
649
716
|
`bo` beneficial owners — same scheme as `data_activation_clients.md`
|
|
650
|
-
§6.
|
|
717
|
+
§6.6), and `id` is ambiguous across the base query's joins, so always
|
|
651
718
|
prefix it: `le.id`.
|
|
652
719
|
|
|
653
720
|
For a **generic-table** workflow there is no alias — the run selects
|
package/dist/index.d.mts
CHANGED
|
@@ -567,9 +567,9 @@ type DataActivationClientLogResponse = {
|
|
|
567
567
|
*/
|
|
568
568
|
rows_ingested?: number;
|
|
569
569
|
/**
|
|
570
|
-
* `failed` when the batch died before enqueueing any row — the fetch itself errored, and `rows_ingested` and `input_files` are 0/[] on such a row. `partial` when the batch ran and at least one row was refused on the way in; the rows that landed are still there. Read `error` for the reason in
|
|
570
|
+
* `processing` from the moment the slice is enqueued until the batch finishes — the column has no default, so this is written, not assumed. `succeeded` is written once by the batch callback, and only over `processing`. `failed` when the batch died before enqueueing any row — the fetch or the enqueue itself errored, and `rows_ingested` and `input_files` are 0/[] on such a row. `partial` when the batch ran and at least one row was refused on the way in; the rows that landed are still there. Read `error` for the reason in the last two.
|
|
571
571
|
*/
|
|
572
|
-
status?: 'succeeded' | 'partial' | 'failed';
|
|
572
|
+
status?: 'processing' | 'succeeded' | 'partial' | 'failed';
|
|
573
573
|
readonly updated_at?: string;
|
|
574
574
|
};
|
|
575
575
|
/**
|
|
@@ -2150,6 +2150,42 @@ type AiAgentInvokeRequest = {
|
|
|
2150
2150
|
[key: string]: unknown;
|
|
2151
2151
|
};
|
|
2152
2152
|
};
|
|
2153
|
+
/**
|
|
2154
|
+
* DataActivationClientBatchResponse
|
|
2155
|
+
*
|
|
2156
|
+
* One record per run. A run fans out into one `DataActivationClientLog` per dataset table it writes into; this is the run itself. To wait on a run, read `closed_at` here rather than reconstructing it from those logs — it is set exactly once, however the run ended.
|
|
2157
|
+
*/
|
|
2158
|
+
type DataActivationClientBatchResponse = {
|
|
2159
|
+
/**
|
|
2160
|
+
* Run identifier, stamped on every Oban job and every per-table log row of this run
|
|
2161
|
+
*/
|
|
2162
|
+
batch_id: string;
|
|
2163
|
+
/**
|
|
2164
|
+
* Owning Data Activation Client ID
|
|
2165
|
+
*/
|
|
2166
|
+
readonly client_id: string;
|
|
2167
|
+
/**
|
|
2168
|
+
* When the run was attempted and exhausted. Null while it is still going. It does not mean rows landed and it does not mean the archive was merged — read `status` for the outcome, and only once this is set.
|
|
2169
|
+
*/
|
|
2170
|
+
readonly closed_at?: string | null;
|
|
2171
|
+
/**
|
|
2172
|
+
* Run record ID
|
|
2173
|
+
*/
|
|
2174
|
+
readonly id?: string;
|
|
2175
|
+
/**
|
|
2176
|
+
* When the run started
|
|
2177
|
+
*/
|
|
2178
|
+
readonly inserted_at?: string;
|
|
2179
|
+
/**
|
|
2180
|
+
* Source rows enqueued for this run. The run's own count; each per-table log keeps its own.
|
|
2181
|
+
*/
|
|
2182
|
+
rows_total?: number;
|
|
2183
|
+
/**
|
|
2184
|
+
* How the run ended. **It means nothing until `closed_at` is set** — a run still in flight always reads `processing`. `failed` when the run died before writing anything; `partial` when it ran and at least one row was refused on the way in; `skipped` when it ran and there was nothing to do, because the file was empty, every row was filtered out, or the client has no contracts.
|
|
2185
|
+
*/
|
|
2186
|
+
status?: 'processing' | 'succeeded' | 'partial' | 'skipped' | 'failed';
|
|
2187
|
+
readonly updated_at?: string;
|
|
2188
|
+
};
|
|
2153
2189
|
/**
|
|
2154
2190
|
* AdvancedMigrationResponse
|
|
2155
2191
|
*
|
|
@@ -3445,6 +3481,18 @@ type SqsResponse = {
|
|
|
3445
3481
|
*/
|
|
3446
3482
|
region: string;
|
|
3447
3483
|
};
|
|
3484
|
+
/**
|
|
3485
|
+
* DataActivationClientBatchListResponse
|
|
3486
|
+
*
|
|
3487
|
+
* Paginated list of data activation client runs
|
|
3488
|
+
*/
|
|
3489
|
+
type DataActivationClientBatchListResponse = {
|
|
3490
|
+
/**
|
|
3491
|
+
* List of data activation client runs
|
|
3492
|
+
*/
|
|
3493
|
+
data: Array<DataActivationClientBatchResponse>;
|
|
3494
|
+
meta: PaginationMeta;
|
|
3495
|
+
};
|
|
3448
3496
|
/**
|
|
3449
3497
|
* PaginationMeta
|
|
3450
3498
|
*
|
|
@@ -3766,11 +3814,11 @@ type DataActivationClientResponse = {
|
|
|
3766
3814
|
* DAC name
|
|
3767
3815
|
*/
|
|
3768
3816
|
name: string;
|
|
3769
|
-
response_extractor?: SimpleTemplateConfigResponse | null;
|
|
3770
3817
|
/**
|
|
3771
3818
|
* Optional row-level Liquid pre-filter. Renders to empty/whitespace → row passes; any non-empty trimmed render → row is skipped (rendered string is the skip reason). Nil/empty body = no filter. Same semantics as InteroperabilityContract.filter_template.
|
|
3772
3819
|
*/
|
|
3773
3820
|
row_filter?: string | null;
|
|
3821
|
+
rows_from_file_template?: SimpleTemplateConfigResponse | null;
|
|
3774
3822
|
/**
|
|
3775
3823
|
* URL-friendly slug (derived from name on insert; immutable)
|
|
3776
3824
|
*/
|
|
@@ -5967,11 +6015,11 @@ type DataActivationClientRequestWritable = {
|
|
|
5967
6015
|
* DAC name
|
|
5968
6016
|
*/
|
|
5969
6017
|
name: string;
|
|
5970
|
-
response_extractor?: SimpleTemplateConfigRequest;
|
|
5971
6018
|
/**
|
|
5972
6019
|
* Optional row-level Liquid pre-filter. Renders to empty/whitespace → row passes; any non-empty trimmed render → row is skipped (rendered string is the skip reason). Nil/empty body = no filter. Same semantics as InteroperabilityContract.filter_template.
|
|
5973
6020
|
*/
|
|
5974
6021
|
row_filter?: string | null;
|
|
6022
|
+
rows_from_file_template?: SimpleTemplateConfigRequest | null;
|
|
5975
6023
|
tool_call: ({
|
|
5976
6024
|
tool_call_type: 'restapi_request';
|
|
5977
6025
|
} & DataActivationClientRestCallRequestWritable) | ({
|
|
@@ -6593,6 +6641,59 @@ type PlatformApiAdvancedMigrationControllerIndexData = {
|
|
|
6593
6641
|
};
|
|
6594
6642
|
url: '/api/v1/tenants/{tenant_slug}/datalakes/{datalake_slug}/advanced-migrations';
|
|
6595
6643
|
};
|
|
6644
|
+
type PlatformApiDataActivationClientControllerBatchesIndexData = {
|
|
6645
|
+
body?: never;
|
|
6646
|
+
path: {
|
|
6647
|
+
/**
|
|
6648
|
+
* Tenant slug
|
|
6649
|
+
*/
|
|
6650
|
+
tenant_slug: string;
|
|
6651
|
+
/**
|
|
6652
|
+
* Datalake slug
|
|
6653
|
+
*/
|
|
6654
|
+
datalake_slug: string;
|
|
6655
|
+
/**
|
|
6656
|
+
* Data Activation Client slug
|
|
6657
|
+
*/
|
|
6658
|
+
slug: string;
|
|
6659
|
+
};
|
|
6660
|
+
query?: {
|
|
6661
|
+
/**
|
|
6662
|
+
* Items per page (1-100). Defaults to the resource's Flop default when omitted.
|
|
6663
|
+
*/
|
|
6664
|
+
page_size?: number;
|
|
6665
|
+
/**
|
|
6666
|
+
* Page number (1-indexed). Defaults to 1 when omitted.
|
|
6667
|
+
*/
|
|
6668
|
+
page?: number;
|
|
6669
|
+
/**
|
|
6670
|
+
* Fields to sort by, in order of precedence. Must appear in the resource schema's Flop `sortable:` list — unknown fields return 422.
|
|
6671
|
+
*/
|
|
6672
|
+
order_by?: Array<string>;
|
|
6673
|
+
/**
|
|
6674
|
+
* Sort direction(s), pair-wise with `order_by`. `asc` or `desc`. Defaults to `asc` per unpaired `order_by` entry.
|
|
6675
|
+
*/
|
|
6676
|
+
order_directions?: Array<'asc' | 'desc'>;
|
|
6677
|
+
/**
|
|
6678
|
+
* Flop-native filter array. URL shape: `?filters[][field]=status&filters[][op]=%3D%3D&filters[][value]=pending` (empty brackets — consecutive `[]` entries group into one filter object per element; indexed brackets parse as a map and fail the array cast with 422). `op` is the symbol, percent-encoded — `%3D%3D` for `==`, `%3E%3D` for `>=` — not a word like `equal`; anything outside the enum above is a 422 before the request reaches Flop. Omit `op` entirely for equality. Unknown fields return 422 via Flop validation at the context layer.
|
|
6679
|
+
*/
|
|
6680
|
+
filters?: Array<{
|
|
6681
|
+
/**
|
|
6682
|
+
* Filterable field name (must be in the resource's `filterable:`)
|
|
6683
|
+
*/
|
|
6684
|
+
field: string;
|
|
6685
|
+
/**
|
|
6686
|
+
* Comparison operator. Defaults to `==` when omitted.
|
|
6687
|
+
*/
|
|
6688
|
+
op?: '==' | '!=' | '<' | '<=' | '>' | '>=' | 'empty' | 'not_empty' | 'like' | 'ilike' | 'like_and' | 'like_or' | 'ilike_and' | 'ilike_or' | 'in' | 'not_in' | 'contains' | 'not_contains';
|
|
6689
|
+
/**
|
|
6690
|
+
* Filter value — shape depends on `field` and `op`.
|
|
6691
|
+
*/
|
|
6692
|
+
value: unknown;
|
|
6693
|
+
}>;
|
|
6694
|
+
};
|
|
6695
|
+
url: '/api/v1/tenants/{tenant_slug}/datalakes/{datalake_slug}/data-activation-clients/{slug}/batches';
|
|
6696
|
+
};
|
|
6596
6697
|
type PlatformApiAiAgentControllerIndexData = {
|
|
6597
6698
|
body?: never;
|
|
6598
6699
|
path: {
|
|
@@ -8353,6 +8454,18 @@ declare function _buildApi(myClient: Client): {
|
|
|
8353
8454
|
response: Response;
|
|
8354
8455
|
}>;
|
|
8355
8456
|
};
|
|
8457
|
+
batches: {
|
|
8458
|
+
list: (tenantSlug: string, datalakeSlug: string, slug: string, query?: PlatformApiDataActivationClientControllerBatchesIndexData["query"]) => Promise<{
|
|
8459
|
+
data: DataActivationClientBatchListResponse;
|
|
8460
|
+
request: Request;
|
|
8461
|
+
response: Response;
|
|
8462
|
+
}>;
|
|
8463
|
+
get: (tenantSlug: string, datalakeSlug: string, slug: string, batchId: string) => Promise<{
|
|
8464
|
+
data: DataActivationClientBatchResponse;
|
|
8465
|
+
request: Request;
|
|
8466
|
+
response: Response;
|
|
8467
|
+
}>;
|
|
8468
|
+
};
|
|
8356
8469
|
};
|
|
8357
8470
|
interoperabilityContracts: {
|
|
8358
8471
|
list: (tenantSlug: string, datalakeSlug: string, query?: PlatformApiInteroperabilityContractControllerIndexData["query"]) => Promise<{
|
|
@@ -8535,5 +8648,5 @@ declare function _buildApi(myClient: Client): {
|
|
|
8535
8648
|
//#region src/index.d.ts
|
|
8536
8649
|
declare function isEnvironmentName(name: string): name is EnvironmentName;
|
|
8537
8650
|
//#endregion
|
|
8538
|
-
export { type ActionStatusUpdaterCloudWatchQueryRequest, type ActionStatusUpdaterRequestWritable, type ActionStatusUpdaterResponse, type ActionStatusUpdaterRestCallRequest, ActionType, type AdvancedMigrationListResponse, type AdvancedMigrationRequest, type AdvancedMigrationResponse, type AgenticWorkflowListResponse, type AgenticWorkflowRequestWritable, type AgenticWorkflowResponse, type AiAgentRequestWritable, type AiAgentResponse, type AlveraApiError, type AlveraClient, type ApiConfig, type ApiDebugConfig, type BatchLogListResponse, type BatchLogResponse, type ConnectedAppListResponse, type ConnectedAppRequestWritable, type ConnectedAppResponse, type CreateActionStatusUpdaterRequest, type CreateAiAgentRequest, type CreateGenericTableRequest, type CreateSessionParams, DEFAULT_ENVIRONMENT, type DataActivationClientListResponse, type DataActivationClientLogListResponse, type DataActivationClientLogResponse, type DataActivationClientRequestWritable, type DataActivationClientResponse, type DataSourceRequest, type DataSourceRequestWritable, type DataSourceResponse, type DatalakeRequestWritable, type DatalakeResponse, type DatasetMetadataOptions, type DatasetSearchOptions, type DatasetSearchResponse, type DerivedLakeTablesResponse, type DownloadUrlResponse, ENVIRONMENTS, type EnvironmentName, type ErrorResponse, type ExecuteActionRequest, type ExecuteActionResponse, type ExecuteSqlMeta, type ExecuteSqlRequest, type ExecuteSqlResponse, type GenericTableColumnRequest, type GenericTableColumnResponse, type GenericTableResponse, type IngestFileRequest, type IngestRequest, type InteroperabilityContractAiAgentRequestWritable, type InteroperabilityContractListResponse, type InteroperabilityContractRequestWritable, type InteroperabilityContractResponse, type InteroperabilityRunRequest, type InteroperabilityRunResponse, type MdmVerifyRequest, type MdmVerifyResponse, type PaginationMeta, type PlatformApi, type ResolvePageRequest, type ResyncTableRequest, type ResyncTableResponse, type RunManuallyRequestWritable, type RunManuallyResponse, type RunWorkflowRequest, type RunWorkflowResponse, type SessionResponse, type SessionResult, type SyncRoutesResponse, type TemplateConfig, type TenantListResponse, type TenantResponse, type TextToSqlRequest, type TextToSqlResponse, ToolIntent, type ToolListResponse, type ToolRequest, type ToolRequestWritable, type ToolResponse, type ToolTwilioRequest, type ToolTwilioRequestWritable, type ToolTwilioResponse, type TwilioRequest, type TwilioRequestWritable, type TwilioResponse, type UpdatePageRequest, type UploadLinkRequest, type UploadLinkResponse, type WorkflowAiAgentRequestWritable, type WorkflowLogListResponse, type WorkflowLogResponse, type WorkflowRunListResponse, type WorkflowRunResponse, createBootstrapSession, createIsolatedPlatformApi, createPlatformApi, createSession, isEnvironmentName, revokeSession };
|
|
8651
|
+
export { type ActionStatusUpdaterCloudWatchQueryRequest, type ActionStatusUpdaterRequestWritable, type ActionStatusUpdaterResponse, type ActionStatusUpdaterRestCallRequest, ActionType, type AdvancedMigrationListResponse, type AdvancedMigrationRequest, type AdvancedMigrationResponse, type AgenticWorkflowListResponse, type AgenticWorkflowRequestWritable, type AgenticWorkflowResponse, type AiAgentRequestWritable, type AiAgentResponse, type AlveraApiError, type AlveraClient, type ApiConfig, type ApiDebugConfig, type BatchLogListResponse, type BatchLogResponse, type ConnectedAppListResponse, type ConnectedAppRequestWritable, type ConnectedAppResponse, type CreateActionStatusUpdaterRequest, type CreateAiAgentRequest, type CreateGenericTableRequest, type CreateSessionParams, DEFAULT_ENVIRONMENT, type DataActivationClientBatchListResponse, type DataActivationClientBatchResponse, type DataActivationClientListResponse, type DataActivationClientLogListResponse, type DataActivationClientLogResponse, type DataActivationClientRequestWritable, type DataActivationClientResponse, type DataSourceRequest, type DataSourceRequestWritable, type DataSourceResponse, type DatalakeRequestWritable, type DatalakeResponse, type DatasetMetadataOptions, type DatasetSearchOptions, type DatasetSearchResponse, type DerivedLakeTablesResponse, type DownloadUrlResponse, ENVIRONMENTS, type EnvironmentName, type ErrorResponse, type ExecuteActionRequest, type ExecuteActionResponse, type ExecuteSqlMeta, type ExecuteSqlRequest, type ExecuteSqlResponse, type GenericTableColumnRequest, type GenericTableColumnResponse, type GenericTableResponse, type IngestFileRequest, type IngestRequest, type InteroperabilityContractAiAgentRequestWritable, type InteroperabilityContractListResponse, type InteroperabilityContractRequestWritable, type InteroperabilityContractResponse, type InteroperabilityRunRequest, type InteroperabilityRunResponse, type MdmVerifyRequest, type MdmVerifyResponse, type PaginationMeta, type PlatformApi, type ResolvePageRequest, type ResyncTableRequest, type ResyncTableResponse, type RunManuallyRequestWritable, type RunManuallyResponse, type RunWorkflowRequest, type RunWorkflowResponse, type SessionResponse, type SessionResult, type SyncRoutesResponse, type TemplateConfig, type TenantListResponse, type TenantResponse, type TextToSqlRequest, type TextToSqlResponse, ToolIntent, type ToolListResponse, type ToolRequest, type ToolRequestWritable, type ToolResponse, type ToolTwilioRequest, type ToolTwilioRequestWritable, type ToolTwilioResponse, type TwilioRequest, type TwilioRequestWritable, type TwilioResponse, type UpdatePageRequest, type UploadLinkRequest, type UploadLinkResponse, type WorkflowAiAgentRequestWritable, type WorkflowLogListResponse, type WorkflowLogResponse, type WorkflowRunListResponse, type WorkflowRunResponse, createBootstrapSession, createIsolatedPlatformApi, createPlatformApi, createSession, isEnvironmentName, revokeSession };
|
|
8539
8652
|
//# sourceMappingURL=index.d.mts.map
|