@postman/postman-plugin 0.3.0 → 0.4.1-rc.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.
Files changed (48) hide show
  1. package/README.md +46 -9
  2. package/dist/hosts/antigravity.js +47 -0
  3. package/dist/hosts/codex-hooks.js +68 -0
  4. package/dist/hosts/codex.js +87 -8
  5. package/dist/hosts/copilot.js +60 -0
  6. package/dist/hosts/index.js +3 -1
  7. package/dist/json-rpc.js +113 -0
  8. package/dist/system.js +40 -3
  9. package/mcp.pi.json +2 -2
  10. package/package.json +1 -1
  11. package/skills/ai-readiness/SKILL.md +40 -44
  12. package/skills/api-discovery/SKILL.md +64 -145
  13. package/skills/api-discovery/reference/orbit.md +17 -5
  14. package/skills/api-documentation/SKILL.md +41 -46
  15. package/skills/api-engineer/SKILL.md +78 -23
  16. package/skills/api-mocking/SKILL.md +117 -163
  17. package/skills/api-monitoring/SKILL.md +52 -129
  18. package/skills/api-simulation/SKILL.md +130 -178
  19. package/skills/api-simulation/reference/sim_yaml_schema.md +41 -103
  20. package/skills/api-testing/SKILL.md +48 -95
  21. package/skills/bootstrap/SKILL.md +123 -224
  22. package/skills/ci-integration/SKILL.md +53 -113
  23. package/skills/collection-schema-v3/SKILL.md +43 -204
  24. package/skills/collection-schema-v3/reference/http.md +150 -0
  25. package/skills/datasets/SKILL.md +89 -315
  26. package/skills/datasets/reference/spreadsheets.md +25 -0
  27. package/skills/flows/SKILL.md +57 -206
  28. package/skills/flows/reference/flow_cli_flags.md +3 -2
  29. package/skills/performance-testing/SKILL.md +46 -62
  30. package/skills/performance-testing/references/jmeter-import/README.md +82 -0
  31. package/skills/performance-testing/references/jmeter-import/import-report.md +52 -0
  32. package/skills/performance-testing/references/jmeter-import/mapping-table.md +95 -0
  33. package/skills/performance-testing/references/jmeter-import/postman-perf-capabilities.md +56 -0
  34. package/skills/performance-testing/references/jmeter-import/script-translation.md +97 -0
  35. package/skills/postman-mcp-server/SKILL.md +53 -59
  36. package/skills/postman-mcp-server/references/docs.md +0 -1
  37. package/skills/postman-mcp-server/references/learn.md +10 -9
  38. package/skills/postman-mcp-server/references/mock.md +0 -1
  39. package/skills/postman-mcp-server/references/search.md +0 -1
  40. package/skills/postman-mcp-server/references/security.md +0 -1
  41. package/skills/postman-mcp-server/references/setup.md +0 -1
  42. package/skills/postman-mcp-server/references/sync.md +0 -1
  43. package/skills/postman-mcp-server/references/test.md +0 -1
  44. package/skills/variables/SKILL.md +44 -87
  45. package/skills/webhook-testing/SKILL.md +103 -0
  46. package/skills/webhook-testing/reference/forwarding.md +10 -0
  47. package/skills/webhook-testing/reference/outbound_webhooks.md +25 -0
  48. package/skills/webhook-testing/reference/webhook_scripts.md +163 -0
@@ -1,324 +1,98 @@
1
1
  ---
2
2
  name: datasets
3
- description: Query CSV and JSON files, spreadsheet exports, and live databases (MySQL, PostgreSQL, SQL Server, or anything with a JDBC driver JAR) as one SQL surface; join across them; save a query as a named view so it can be rerun without re-pasting the SQL; then drive a collection run one iteration per row — feeding it the rows a query returns instead of a hardcoded data file — or read rows from scripts via `pm.datasets()`. Use when the user wants to run or loop a collection over rows of test data, parameterize a run from a CSV or spreadsheet or database table, query or join data across files and tables, save or rerun a query without pasting it again, use a query's result rows as the input for a run in place of hardcoded JSON or a data file, point Postman at a JDBC driver, work out where database credentials get stored, or names a Postman dataset or view. Covers `postman dataset` (`source`, `view`, `query`, `jdbc`) and `--iteration-data-dataset`/`--iteration-data-view`/`--dataset` on `collection run`.
3
+ description: Use when a collection needs queried or joined test inputs, a reusable named view, spreadsheet worksheet data, live database rows, or script access through pm.datasets(). Chooses between a simple iteration file and a dataset while preserving query semantics, portability, and credential boundaries. Use for requests such as "run this collection over database rows".
4
4
  ---
5
5
 
6
6
  # Datasets
7
7
 
8
- ## Required CLI version
9
-
10
- This skill documents the dataset commands as they behave **after**
11
- postman-cli#1323 (AUTO-987, the spurious `No authorization data found`
12
- notice) and postman-cli#1340 (AUTO-999/AUTO-998, one datasource per
13
- worksheet plus the help-text fixes). Both are needed; 1.62.0 has neither.
14
- Check with `postman --version` before trusting the worksheet and
15
- auth-notice rules below, and on an older CLI expect `source add --file
16
- book.xlsx` to add a workbook as a single unqueryable source (in a cloud
17
- dataset too), `source update --file book.xlsx` to be accepted and rewrite the
18
- source to `format: csv`, and every logged-out `--iteration-data-dataset` run
19
- to print the notice.
20
-
21
- ## Overview
22
-
23
- A dataset is a Postman entity that names one or more *datasources* and
24
- presents them as SQL tables. It lives either in a Postman workspace or in the
25
- repository, and the same commands work on both — with one carve-out, a
26
- spreadsheet source, covered below. It is not a data file — it is
27
- a layer over data files and databases, and the value is in that layer:
28
- heterogeneous
29
- sources (a CSV and a Postgres table) become joinable in one query, and a
30
- saved *view* turns a query into a named, reusable result set that a
31
- collection run can iterate.
32
-
33
- Local and cloud are the same commands. Every verb that acts on an *existing*
34
- dataset — `get`, `query`, `delete`, and every `source` and `view`
35
- subcommand — takes either a `.dataset.yaml` path or a cloud dataset id and
36
- routes accordingly. Two verbs name a location instead of an existing
37
- dataset: `list` takes a path or directory (its cloud form is
38
- `-w <workspaceId>`), and `create` takes the path to write (its cloud form is
39
- `-w` with no path, since the id does not exist yet). `jdbc inspect` takes
40
- neither — it reads a driver JAR and touches no dataset at all.
41
-
42
- There is no `dataset push` verb — but that does not mean local and cloud are
43
- sealed off from each other. Datasets are a workspace entity, so `postman
44
- workspace push` persists them in the bound workspace alongside collections,
45
- environments and the rest, making that context available to future work and
46
- for sharing with others. `postman workspace pull` brings them back down. Reach
47
- for those when the whole repo should move; the `dataset` verbs below are for
48
- working on one dataset in place.
49
-
50
- ## Core knowledge
51
-
52
- - **Datasets are the current way to drive a run from data.** They supersede
53
- passing a flat file with `-d`/`--iteration-data`: a dataset gives the same
54
- row-per-iteration behaviour, and on top of it SQL to filter and shape rows,
55
- joins across several sources, a live database instead of an export, named
56
- views that can be rerun, and `pm.datasets()` access from scripts. Reach for
57
- a dataset by default when someone wants to run a collection over rows of
58
- data; `-d` remains available for a one-off file and stays the lighter option
59
- when nothing more is wanted.
60
-
61
- - **A spreadsheet becomes one source per worksheet, not one source — and
62
- only in a local dataset.** The engine reads Excel and OpenDocument
63
- workbooks (`xlsx`, `xls`, `ods`) as well as CSV and JSON, and
64
- `source add --file book.xlsx` enumerates the sheets and adds each as its own
65
- datasource — matching what the Postman app does. There is no flag for
66
- picking a sheet, by design. Three boundaries come before anything else:
67
-
68
- - **Local datasets only.** Adding a workbook to a *cloud* dataset is
69
- refused with `SPREADSHEET_CLOUD_UNSUPPORTED`, with or without `--upload`:
70
- a cloud add posts one datasource with no worksheet selector and the cloud
71
- service is never handed the bytes to fan the workbook out itself, so it
72
- would persist exactly the unqueryable source the local path exists to
73
- prevent. CSV and JSON work on both. This is the carve-out to
74
- "local and cloud are the same commands" — put the workbook in a local
75
- `.dataset.yaml`.
76
- - **`xlsx`, `xls` and `ods` only.** `.xlsm`, `.xlsb` and `.numbers` are
77
- unmistakably workbooks that the engine cannot read, so extension
78
- inference refuses them with `WORKBOOK_FORMAT_UNSUPPORTED` rather than
79
- letting them fall through to the `csv` default and write a source that
80
- fails every query. Re-save as `.xlsx`, or pass `--format csv` only if the
81
- file really is delimited text.
82
- - **`-n` is optional for a workbook, and ignored.** It is required for
83
- every other source kind, but worksheet sources are named after their
84
- sheets, so a `-n` passed here changes nothing and earns a
85
- `NAME_UNUSED_FOR_SPREADSHEET` warning.
86
-
87
- Each source is named `source_<sheet>`, with anything outside
88
- `[a-zA-Z0-9_]` replaced by `_`, and `_2`/`_3` appended on collision —
89
- collision being judged on the engine's *table* key rather than on the
90
- literal name, so two sheets that normalise onto one table are given
91
- distinct names instead of registering one table twice and failing every
92
- query on the dataset. A workbook with People, Orders and "Sales Q3 2026"
93
- therefore gives `source_People`, `source_Orders` and
94
- `source_Sales_Q3_2026`. The `-n` you passed does **not** appear in them —
95
- the scheme matches the Postman app (and DCS server-side), so a workbook
96
- added from the CLI and the same one added from the app produce identical
97
- source names and survive a push/pull round trip.
98
-
99
- Those are *source* names, and a source name is not always a table name.
100
- **Take the queryable name from the command's own output instead of deriving
101
- it.** `source add` prints a line per sheet —
102
- `"source_People" (id: …) from worksheet "People"` — and appends
103
- `, queryable as "<table>"` whenever the table differs, so a `売上` sheet is
104
- reported as `source___`, queryable as `source`, and `FROM source` is the
105
- query. Under `--json` the same thing arrives as `sources[]`, one
106
- `{id, name, worksheet, table}` entry per worksheet and present for every
107
- workbook add however many sheets it found; `table` is the field a `FROM`
108
- clause takes. Still don't copy `name` into a `FROM` clause verbatim, and
109
- note that a `source_` prefix is correct here and wrong for a source you
110
- named yourself, so do not carry the habit across.
111
-
112
- **`source update` cannot make a worksheet source, and now refuses to try.**
113
- Both halves are hard refusals with a code, and nothing is written:
114
- `--file <workbook>` fails `SPREADSHEET_FILE_NOT_UPDATABLE` (`.xlsm`,
115
- `.xlsb` and `.numbers` included) and `--format xlsx|xls|ods` fails
116
- `SPREADSHEET_FORMAT_NOT_UPDATABLE`, because the command patches `format`
117
- and `location` field-wise and has no way to pin a worksheet. What is still
118
- *allowed* and still destructive is `update --file other.csv` on a source
119
- that already has a worksheet: that patch carries no `source_options`, so
120
- the stale `spreadsheet.worksheet` selector stays pinned to a file with no
121
- worksheets and the source stops being queryable (AUTO-1000). Remove the
122
- source and re-add the workbook with `source add`.
123
-
124
- - **`--format` is not validated.** Its help text lists the real formats, but
125
- the flag accepts any string and writes it straight into the manifest, so a
126
- typo becomes a source that fails only later at query time. Pass it only to
127
- override inference deliberately; otherwise let the file extension speak.
128
- - **A datasource's table name is its `name` *normalised*, not its `name`.**
129
- Before exposing a source as a table the engine lowercases the name,
130
- collapses every run of `_` to a single `_`, and strips leading and trailing
131
- `_`. So `-n users` really is `FROM users`, but `-n Sales__Q3_` is
132
- `FROM sales_q3` — and `FROM Sales__Q3_`, the name you passed and the name
133
- the CLI echoes back, fails `SQL_UNKNOWN_TABLE`. Case alone is safe (SQL
134
- identifiers are case-insensitive, so `FROM MixedCase` still finds
135
- `mixedcase`); underscore runs and edge underscores are not. Keep source
136
- names already-normalised and the two can never diverge. A workbook add
137
- reports each sheet's table itself (`queryable as …`, or `sources[].table`
138
- under `--json`); for anything else, on the federated path
139
- `SELECT name FROM sqlite_master WHERE type='table'` lists the real ones.
140
- **The CLI's own `-h` examples say `FROM source_users`, and they are
141
- wrong** — there is no `source_` prefixing for a source you named
142
- yourself, and `source_users` fails `SQL_UNKNOWN_TABLE`. Trust the normalised source
143
- name, not the example text.
144
- - **Federated vs native is the central query decision.** With no `--source`,
145
- the query runs through a federated SQLite layer that can join across every
146
- *federatable* source in the dataset — which is all of them except JDBC, per
147
- the next rule. With `--source <name>`, it is sent to that one
148
- datasource in *its own SQL dialect* — which is the only thing that works
149
- for JDBC sources, and what you want for dialect-specific SQL
150
- (`now() - interval '1 day'`). `dataset query -s` and
151
- `dataset view create -s` take the same reference. They are different
152
- execution paths, not fallbacks for each other — adding or dropping
153
- `--source` to make a failing query work changes what the query *means*.
154
- - **JDBC is the one source type that cannot federate.** A native
155
- `--type mysql|postgresql|sqlserver` source *does* join against a CSV in one
156
- federated query, which is the main reason to build a mixed dataset. A
157
- `--type jdbc` source does not appear in the federated layer at all: query
158
- it without `--source` and it fails `SQL_UNKNOWN_TABLE`, exactly as a
159
- misspelled table would. So a JDBC source cannot be joined to anything —
160
- if you need that join, add the database as its native type instead.
161
- - **Local does not mean free, and the plan gate keys off source type, not
162
- dataset location.** CSV/JSON sources run fully offline, logged out. Any
163
- *database* source — including one inside a purely local YAML — forces
164
- authentication and an entitlement check: MySQL and PostgreSQL need a paid
165
- plan, and **JDBC and SQL Server need Enterprise**
166
- (`… data sources require an Enterprise plan.`, HTTP 402).
167
- - **A view's result set is iteration data.** `collection run
168
- --iteration-data-dataset <pathOrId> --iteration-data-view <nameOrId>`
169
- runs one iteration per row, with each column bound as a variable
170
- (`{{name}}`). Both flags are required together, and the pair is mutually
171
- exclusive with `-d/--iteration-data`.
172
- - **On a dataset run, `No authorization data found` means a source really
173
- does need auth.** A file-backed dataset needs none, and a logged-out run
174
- over one is silent. So if that line appears on an
175
- `--iteration-data-dataset` run, read it as signal: a **database** source is
176
- in play — `jdbc`, `mysql`, `postgres`/`postgresql` or `sqlserver`, and a
177
- `postmancloudfile` source is *not* one of those and does not trigger it —
178
- or you passed a cloud dataset id or a cloud collection, or the manifest
179
- could not be read, those last three all landing on the same fail-closed
180
- branch. What it is *not* is a verdict on the run — a plain
181
- `collection run` with no dataset flags still prints it whenever you are
182
- logged out, because it comes from the run command rather than anything
183
- dataset-related.
184
- - **`--dataset <pathOrDir>` is the other consumption path** — repeatable,
185
- and it exposes datasets to scripts as `pm.datasets(<id>)` rather than
186
- driving iterations. Resolution is lazy: a run that never calls
187
- `pm.datasets` parses nothing and needs no auth. An unparseable YAML is
188
- skipped with a `[pm.datasets] skipped …` warning, not a failed run — so a
189
- silently absent dataset looks like a script bug.
190
- - **Query parameters are positional.** `$1, $2` in the SQL, `-p` values in
191
- order. Views can be parameterized too, but a parameterized view **cannot**
192
- drive iteration data — `collection run` has nowhere to pass `-p`, and it
193
- fails as an opaque execution error. Keep iteration views parameter-free.
194
- - **Dataset commands never touch `.postman/resources.yaml`.** Unlike mocks,
195
- there is no repo-level registry entry to commit or clean up — the
196
- `.dataset.yaml` and its `data_dir` are the whole artifact.
197
- - **`data_dir` is not only your data.** The local engine writes its own state
198
- in there next to the copied files — `data.db`, `meta.db`, `daemon.log`,
199
- `config/`, and a uuid-named directory. Commit the manifest and the source
200
- files; ignore the rest, or the repo starts carrying a query cache and a log.
201
- `daemon.log` is also the first place to look when the engine itself, rather
202
- than a query, is what failed.
203
-
204
- ## Process
205
-
206
- 1. **Scaffold.** `postman dataset create ./postman/datasets/NAME/NAME.dataset.yaml
207
- --name "NAME"` writes a four-line manifest with a generated id and
208
- `data_dir: .resources`. The cloud form is `create --name "NAME" -w <workspaceId>`
209
- with no path.
210
- 2. **Attach sources.** `postman dataset source add -d <dataset> -n <table>
211
- --file ./users.csv` **copies** the file into `data_dir` — pass
212
- `--ref-only` to reference it in place instead — but note it records an
213
- **absolute** path, so a `--ref-only` dataset is machine-local and does not
214
- survive being committed and cloned elsewhere. Extensions
215
- pick the format only when `--format` is absent; contents are never
216
- sniffed, so a `.txt` holding JSON needs `--format json`. For a cloud
217
- dataset, `--file` alone registers a *local-filesystem* source read by the
218
- local engine; `--upload` is what actually puts the data in the cloud.
219
- Either way a cloud dataset takes csv and json only — a workbook is refused
220
- there.
221
- 3. **For a *JDBC* source, start from `jdbc inspect`.**
222
- `postman dataset jdbc inspect ./drivers/pg.jar` maps straight onto the
223
- `source add` flags: `suggestedUrlTemplate` → `--url-template`,
224
- `templateVariables` → `--var`, `connectionProperties` → `--prop`,
225
- `driverClass` → `--driver-class`. A second source on the same database
226
- reuses all of it with `--from-source <name>`. A connection test runs
227
- before the write, so a JDBC source that cannot connect is never persisted
228
- (`--no-test` opts out). A native `--type mysql|postgresql|sqlserver`
229
- source needs none of this — no driver JAR, no inspect step, just
230
- `--host/--port/--database/--user/--password` — and it is **not**
231
- connection-tested before the write, so run `source test` yourself after
232
- adding one.
233
- 4. **Explore with ad-hoc SQL before saving anything.**
234
- `postman dataset query <dataset> -q "SELECT …"`. Get the query right
235
- here — a view is just a query you have already proven.
236
- 5. **Save the query as a view.** `postman dataset view create -d <dataset>
237
- -n "Active" -q "SELECT …"`, then `view run "Active" -d <dataset>` to
238
- confirm the rows. This is the step that makes the dataset usable by a
239
- run.
240
- 6. **Drive the run.** `postman collection run <collection>
241
- --iteration-data-dataset <dataset> --iteration-data-view "Active"`.
242
- Confirm the iteration count matches the row count — that is the only
243
- proof the wiring works.
244
-
245
- ## Critical rules
246
-
247
- 1. **Secrets are only avoidable on the JDBC path, and that decides which
248
- source type to use.** A credential passed as a **literal** lands in three
249
- places: `ps` output, shell history, **and clear text in the dataset YAML**
250
- (or the cloud request body). The CLI warns about exactly those three, and
251
- only for literals. What differs by source type is whether there is an
252
- alternative:
253
- - **JDBC (`--var`, `--prop`): yes, and it avoids all three.**
254
- `--var name=vault:<vaultId>/<secretId>` stores a `{$vaultId,$secretId}`
255
- pointer and resolves it at query time, so the secret itself reaches none
256
- of the three — only the reference travels through argv. `--vars-file`
257
- reads the same values from a JSON file and `--vars-file -` from stdin,
258
- which is the one way to keep a value out of `ps` and shell history; it
259
- accepts vault refs too, and a *literal* passed that way still lands in
260
- the YAML in clear text. Local Vault secrets are not supported — Shared
261
- Vault only. A literal secret in `--url-template` is rejected outright: a
262
- literal has no `{{name}}` to route through `--var`, so nothing could
263
- mask it.
264
- - **Native `--type mysql|postgresql|sqlserver` (`--user`, `--password`):
265
- no.** The CLI says so on every write —
266
- `Secret references for database credentials are not yet supported by
267
- Postman CLI.` There is no vault form of these flags. The credentials
268
- land in the YAML in clear text or the source does not exist.
269
-
270
- So when credentials must not sit in a committed file, reach for
271
- `--type jdbc` with Vault refs rather than the native type for the same
272
- database. Otherwise treat that YAML as a secret-bearing file and keep it
273
- out of version control.
274
- 2. **"The dataset operation failed with a server error. Please retry." is
275
- usually not a server error and retrying will not help.** It is the
276
- generic wrapper over engine errors, including your SQL being wrong.
277
- Re-run with `--debug` to get the real code — `engineCode=SQL_UNKNOWN_TABLE`
278
- for a bad table name, and so on. Read that before changing anything.
279
- 3. **When a query fails, isolate the layer with
280
- `postman dataset source test -d <dataset> -n <source>`.** It opens and
281
- closes a real connection using the stored config, resolving Vault
282
- references the way a query would, which separates "the source is broken"
283
- from "the SQL is wrong". File and URL sources have no connection and
284
- report `SOURCE_NOT_TESTABLE` — that is the expected answer, not a fault.
285
- 4. **`--dataset` on a cloud collection does not scope access.** A script can
286
- call `pm.datasets(<anyId>)` for any dataset the logged-in session can
287
- read. Only run collections you trust against a logged-in cloud session.
288
- 5. **`dataset delete` is permanent and deliberately asymmetric** — it
289
- removes the manifest but preserves the source files, because references
290
- can cross directory boundaries. An empty `data_dir` is removed unless
291
- `--keep-resources` is passed. Confirm before running it on a cloud id,
292
- where there is no file left behind to recover from.
293
- 6. **Pass `--json` when parsing.** Both success and failure go to stdout, so
294
- `--json 2>/dev/null | jq .` works either way, and failures carry a stable
295
- `error.code` (`CONNECTION_FAILED`, `DRIVER_CLASS_AMBIGUOUS`,
296
- `CONFIG_VALUE_MISSING`, …) plus `remediation`. Branch on the code, never
297
- on the prose.
298
-
299
- ## Anti-patterns
300
-
301
- - **Don't add a database source to make a demo "more realistic."** It
302
- converts a zero-setup offline dataset into one that needs login, a paid
303
- plan, network reachability, and (for JDBC/SQL Server) Enterprise. Use CSV
304
- unless the live data is the point.
305
- - **Don't run `postman dataset list` with no arguments** expecting the local
306
- datasets. Bare `list` is the *cloud* form and errors without `-w` outside
307
- a Postman-managed project; pass a path or directory for local ones.
308
- - **Don't hand-edit `.dataset.yaml` to add a source.** `source add` runs the
309
- connection test (JDBC), id generation, and secret validation that a
310
- hand-edited entry skips — and the resolver re-inspects every YAML
311
- precisely so a hand-edited file cannot bypass the source gate.
8
+ A dataset gives files and database sources a queryable interface; a saved view
9
+ turns the query into reusable test input. That is useful when filtering,
10
+ joining, or refreshing rows is part of the test. A one-off CSV/JSON run can
11
+ stay with `collection run -d`; a dataset should earn its extra configuration.
12
+
13
+ ## Choose the data and execution path
14
+
15
+ 1. Prefer local file sources for reproducible fixtures. A live database is
16
+ useful when current data is the point, but adds authentication, entitlement,
17
+ network, and credential requirements even in a local `.dataset.yaml`.
18
+ Check `postman dataset <action> -h` and the actual source capability before
19
+ promising a workflow; source support can vary with the installed CLI.
20
+ 2. Use the default federated SQLite query path to join supported sources.
21
+ `--source <name>` instead sends SQL to one source in its native dialect.
22
+ Switching modes to silence a SQL error changes query semantics. JDBC
23
+ requires the native path and cannot join in the federated layer; native
24
+ database connectors can support federation.
25
+ 3. Choose credentials before choosing a database connector. JDBC variables
26
+ and properties accept shared-vault references such as
27
+ `vault:<vaultId>/<secretId>`, resolved at query time. Native database
28
+ credentials are stored literally in dataset configuration on the documented
29
+ CLI surface; inspect current support before use, and keep secret-bearing
30
+ configuration out of Git. Literal values passed through stdin avoid argv
31
+ exposure but can still be persisted in YAML. See **variables** for vault
32
+ handling. A connector that enables a join may have a worse credential
33
+ boundary than JDBC; do not hide that tradeoff.
34
+ 4. Choose iteration or script access deliberately. The paired
35
+ `--iteration-data-dataset <path-or-id>` and
36
+ `--iteration-data-view <name-or-id>` flags feed one row per collection
37
+ iteration, with columns exposed as variables. They exclude `-d` and require
38
+ a parameter-free view because the runner has no query-parameter input.
39
+ Repeatable `--dataset <path-or-dir>` instead exposes `pm.datasets()` to
40
+ scripts; it does not itself create row-driven iterations.
41
+
42
+ ## Build a portable, queryable artifact
43
+
44
+ Create a local manifest with `postman dataset create <path.dataset.yaml>
45
+ --name <name>`, then attach sources with `dataset source add`. Source commands
46
+ supply IDs and validation that hand-written entries can miss. Existing-dataset
47
+ commands accept a local path or workspace ID; `list` needs a local path for
48
+ local discovery, while workspace create/list use `--workspace`.
49
+
50
+ File sources are copied into `data_dir` unless `--ref-only` is used. That option
51
+ records absolute paths and makes the dataset machine-specific. For a workspace
52
+ dataset, adding `--file` alone registers a local filesystem source; `--upload`
53
+ is what uploads bytes. Use **bootstrap**'s workspace sync when publishing the
54
+ whole project; there is no separate `dataset push`.
55
+
56
+ For spreadsheet sources, use the worksheet-aware guidance in
57
+ [Spreadsheet sources](reference/spreadsheets.md). For ordinary source names,
58
+ prefer normalized identifiers: table names lowercase, collapse repeated
59
+ underscores, and strip edge underscores. A source called `users` is queried
60
+ as `users`, not `source_users`. Verify actual tables before interpreting an
61
+ unknown-table error as missing data.
62
+
63
+ For JDBC, `dataset jdbc inspect <driver.jar>` supplies driver class, URL
64
+ template, variables, and properties for `source add`; `--from-source` can reuse
65
+ a connection. JDBC addition tests connectivity unless disabled; native source
66
+ addition needs a separate `dataset source test`. This distinction prevents
67
+ mistaking a saved source for a working connection.
68
+
69
+ Prove the query with `dataset query` before saving it with `dataset view create`,
70
+ then run the view. Query parameters are positional (`$1`, `$2`, with `-p`
71
+ values in order). Commit the manifest and intended source files; keep engine
72
+ state such as `data.db`, `meta.db`, `daemon.log`, and caches out of the repo.
73
+ Dataset commands do not create a `.postman/resources.yaml` registry entry.
74
+ Deletion removes the manifest but preserves source files that may be shared.
75
+ Deleting a workspace dataset is permanent; establish that intent rather than
76
+ treating deletion as a way to repair a query.
77
+
78
+ ## Interpret failures and results
79
+
80
+ A generic server-error wrapper can hide SQL or connection errors. Use structured
81
+ `--json` errors and their remediation, or `--debug` when necessary, to identify
82
+ the layer before retrying. `source test` separates database connectivity from
83
+ SQL errors; file/URL sources have no connection to test. Engine startup failures
84
+ may need `data_dir`'s daemon log rather than a different query.
85
+
86
+ Script dataset access is lazy, and invalid YAML can be skipped with a warning
87
+ rather than failing the run. On a hosted collection, `--dataset` is not an
88
+ access-control boundary: scripts can access other datasets readable by the
89
+ session. Inspect the collection's data access before running untrusted scripts
90
+ with that session.
312
91
 
313
92
  ## Verification
314
93
 
315
- A dataset is not working because `create` and `source add` exited 0 — those
316
- prove only that the write went through: a manifest locally, a workspace
317
- entity in the cloud, and on the JDBC path a connection that opened, unless
318
- `--no-test` skipped that test. None of it proves a query returns rows. Run an actual query and state
319
- the row count and columns you got back. For a run, state the iteration count
320
- and confirm it equals the view's row count; three rows producing one
321
- iteration means the view, not the collection, is what to look at. Say which
322
- execution path ran (federated or `--source` native) and whether the dataset
323
- was local or cloud — that determines whether the numbers reflect live data
324
- or a copied snapshot in `data_dir`.
94
+ Report the queried columns and row count, local/workspace location, live versus
95
+ copied sources, and federated versus native execution. For iteration runs,
96
+ compare the actual iteration count with the intended view rows and configured
97
+ limits. Matching counts establishes wiring, not that the data covers every
98
+ behavior the test needs. Creating a manifest alone proves neither.
@@ -0,0 +1,25 @@
1
+ # Spreadsheet sources
2
+
3
+ Use a local dataset for Excel or OpenDocument workbooks. The worksheet-aware
4
+ source-add path creates one datasource per sheet; treating the entire workbook
5
+ as one CSV source leaves an artifact that can be saved but not queried.
6
+
7
+ - Supported workbook formats are `xlsx`, `xls`, and `ods`. Re-save other
8
+ workbook formats rather than forcing `--format csv` onto binary data.
9
+ - `source add --file <workbook>` names sources from sheets; `-n` does not
10
+ rename them or select one sheet. Workspace dataset adds do not support this
11
+ worksheet expansion, even with `--upload`; use local workbooks or deliberate
12
+ CSV/JSON exports for that branch.
13
+ - Read `sources[].table` in JSON output for each queryable identifier. Sheet
14
+ names can normalize and collide, so deriving a SQL table from a display name
15
+ or adding a `source_` prefix by habit can query the wrong identifier.
16
+ - Remove and re-add to replace a worksheet source. `source update` cannot
17
+ establish a worksheet selector; replacing its file with CSV can leave a
18
+ stale worksheet selector attached to data that has no worksheets.
19
+ - Verify that addition returned one source per intended sheet and query the
20
+ needed tables. Older CLI behavior can register a single unusable workbook
21
+ source; successful creation is insufficient evidence of worksheet support.
22
+
23
+ Let file extensions infer formats unless the contents require an explicit
24
+ supported override. A format string accepted by the CLI can still fail when
25
+ the query engine reads the source.