@xapps-platform/cli 0.1.1

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/README.md ADDED
@@ -0,0 +1,560 @@
1
+ # `@xapps-platform/cli`
2
+
3
+ Developer CLI for Xapps manifest workflows.
4
+
5
+ Current source/package note:
6
+
7
+ - monorepo source path: `packages/xapps-cli`
8
+ - workspace package name: `@xapps-platform/cli`
9
+ - public release name: `@xapps-platform/cli`
10
+
11
+ ## Supported Surface
12
+
13
+ Public/stable publish workflow subset:
14
+
15
+ - `xapps import --from <openapi> --out <manifest.json> [--fetch-timeout-ms <n>]`
16
+ - `xapps init --out <directory>`
17
+ - `xapps validate --from <manifest.json>`
18
+ - `xapps test --from <manifest.json> --vectors <vectors.json>`
19
+ - `xapps publish --from <manifest.json> [--yes] [--out <file-or-dir>] [--dry-run] [--publish-url <url>] [--publisher-gateway-url <url>] [--target-client-slug <slug>] [--token <token>] [--api-key <key>] [--signing-key <key>] [--version-conflict <fail|allow>] [--release-channel <name>] [--registry-target <name>] [--idempotency-key <key>] [--timeout-ms <n>] [--retry-attempts <n>] [--retry-backoff-ms <n>]`
20
+ - `xapps logs [--from <bundle.json> | --dir <path>] [--limit <n>] [--json] [--logs-url <url>] [--token <token>] [--api-key <key>] [--cursor <value>] [--lease-id <value>] [--checkpoint <value>] [--severity <value>] [--since <iso>] [--until <iso>] [--follow] [--follow-interval-ms <n>] [--follow-max-cycles <n>] [--follow-cursor-file <path>] [--timeout-ms <n>] [--retry-attempts <n>] [--retry-backoff-ms <n>]`
21
+ - `xapps publisher endpoint credential set --gateway-url <url> [--endpoint-id <id> | --xapp-slug <slug> --env <env>] --auth-type <api-key|...> --header-name <name> (--secret-env <ENV> | --secret-stdin | --secret-ref <ref>) [--api-key <key> | --token <token>] [--json]`
22
+ - `xapps publisher endpoint credential ensure --gateway-url <url> [--endpoint-id <id> | --xapp-slug <slug> --env <env>] --auth-type <api-key|...> --header-name <name> (--secret-env <ENV> | --secret-stdin | --secret-ref <ref>) [--api-key <key> | --token <token>] [--json]`
23
+
24
+ Repo-only/internal helpers stay available but are not part of the supported public package contract.
25
+
26
+ Current proven checkpoint:
27
+
28
+ - Repo automation currently depends on:
29
+ - `xapps validate`
30
+ - `xapps publish`
31
+ - `xapps publisher endpoint credential ensure`
32
+ - Built-package smoke currently verifies:
33
+ - `xapps init`
34
+ - `xapps import`
35
+ - `xapps validate`
36
+ - `xapps test`
37
+ - `xapps publish`
38
+ - `xapps logs`
39
+ - Packed-artifact smoke now verifies the same local publish subset from the packed tarball entrypoint and also exercises the remote publisher/gateway flow for:
40
+ - `xapps publish --publisher-gateway-url ... --target-client-slug ...`
41
+ - `xapps publisher endpoint credential ensure --gateway-url ... --xapp-slug ... --target-client-slug ...`
42
+ - Manifest validation on the supported surface now comes from the shared `@xapps-platform/xapp-manifest` package, re-exported through `@xapps-platform/server-sdk`.
43
+ - Source-level CLI tests already cover:
44
+ - `xapps import`
45
+ - `xapps test`
46
+ - `xapps logs`
47
+ - `xapps publisher endpoint credential set`
48
+ - `xapps publisher endpoint credential ensure`
49
+
50
+ Smoke commands:
51
+
52
+ ```bash
53
+ npm run smoke --workspace packages/xapps-cli
54
+ npm run smoke:packed --workspace packages/xapps-cli
55
+ ```
56
+
57
+ ## Install
58
+
59
+ ```bash
60
+ npm install -D @xapps-platform/cli
61
+ ```
62
+
63
+ Note:
64
+
65
+ - This package is now in first public release-candidate shape for the supported non-breaking publish subset.
66
+ - This README documents only that supported external contract; it does not claim the whole CLI surface is public/stable.
67
+
68
+ ## Commands (baseline)
69
+
70
+ - `xapps import --from <openapi> --out <manifest.json> [--fetch-timeout-ms <n>]`
71
+ - `xapps init --out <directory>`
72
+ - `xapps validate --from <manifest.json>`
73
+ - `xapps dev --from <manifest.json> [--dry-run <request.json>]` (local helper; not part of the supported public package contract)
74
+ - `xapps dev status refs [--json]` (internal-repo helper)
75
+ - `xapps dev check v1 [--json]` (internal-repo helper)
76
+ - `xapps dev check flow --name <pay-per-request|guard-orchestration|xplace-certs> [--json] [--run] [--artifacts-dir <dir>]` (internal-repo helper)
77
+ - `xapps dev check flow --from <flow.json> [--json] [--run] [--artifacts-dir <dir>]` (custom app-owned flow file)
78
+ - `xapps dev check flow init --out <flow.json> --type <ai-artifacts|manual-loop> [--flow-id <id>] [--manifest <path>] [--policy <path>] [--smoke-script <path>] [--json]` (starter template generator)
79
+ - `xapps dev check flow lint --from <flow.json> [--json]` (custom flow sanity checks)
80
+ - `xapps test --from <manifest.json> --vectors <vectors.json>`
81
+ - `xapps publish --from <manifest.json> [--yes] [--out <file-or-dir>] [--dry-run] [--publish-url <url>] [--publisher-gateway-url <url>] [--target-client-slug <slug>] [--token <token>] [--api-key <key>] [--signing-key <key>] [--version-conflict <fail|allow>] [--release-channel <name>] [--registry-target <name>] [--idempotency-key <key>] [--timeout-ms <n>] [--retry-attempts <n>] [--retry-backoff-ms <n>]`
82
+ - `xapps logs [--from <bundle.json> | --dir <path>] [--limit <n>] [--json] [--logs-url <url>] [--token <token>] [--api-key <key>] [--cursor <value>] [--lease-id <value>] [--checkpoint <value>] [--severity <value>] [--since <iso>] [--until <iso>] [--follow] [--follow-interval-ms <n>] [--follow-max-cycles <n>] [--follow-cursor-file <path>] [--timeout-ms <n>] [--retry-attempts <n>] [--retry-backoff-ms <n>]`
83
+ - `xapps context export --from <manifest.json> [--out <file>] [--preset <internal-v1>]` (internal preset is repo-only)
84
+ - `xapps tunnel --target <base-url> [--allow-target-hosts <csv>] [--session-id <id>] [--session-file <path>] [--session-policy <reuse|require|rotate>] [--listen-port <port>] [--host <host>] [--require-auth-token <tok>] [--upstream-timeout-ms <n>] [--retry-attempts <n>] [--retry-backoff-ms <n>]` (local relay helper; not part of the supported public package contract)
85
+ - `xapps ai plan --mode internal --from <manifest.json> [--json] [--mocks-dir <dir> | --mocks <csv>] [--guidance <text> | --guidance-file <file> | --ask-guidance] [--llm] [--llm-model <model>] [--llm-api-key <key>] [--llm-base-url <url>] [--llm-timeout-ms <n>] [--apply-manifest-hints]` (mock-aware plan + optional LLM suggestions; apply is optional)
86
+ - `xapps ai check --mode internal --plan <plan.json> [--policy <policy.json> | --policy-preset <internal-readonly>] [--json]` (read-only internal check)
87
+ - `xapps publisher endpoint credential set --gateway-url <url> [--endpoint-id <id> | --xapp-slug <slug> --env <env>] --auth-type <api-key|...> --header-name <name> (--secret-env <ENV> | --secret-stdin | --secret-ref <ref>) [--api-key <key> | --token <token>] [--json]`
88
+ - `xapps publisher endpoint credential ensure --gateway-url <url> [--endpoint-id <id> | --xapp-slug <slug> --env <env>] --auth-type <api-key|...> --header-name <name> (--secret-env <ENV> | --secret-stdin | --secret-ref <ref>) [--api-key <key> | --token <token>] [--json]`
89
+
90
+ ## Notes
91
+
92
+ - Shared auth profiles are supported via `~/.xapps/config` JSON and per-command `--profile` (or env `XAPPS_CLI_PROFILE`).
93
+ - Remote auth supports Bearer (`--token` / `XAPPS_CLI_TOKEN`) and API key (`--api-key` / `XAPPS_CLI_API_KEY`) headers.
94
+ - Precedence is `CLI flags > env vars > selected profile`.
95
+ - Publish now includes explicit release confirmation; in non-interactive flows use `--yes`.
96
+ - Publish is tenant-aware: set `manifest.target_client_id`, or (when using `--publisher-gateway-url`) pass `--target-client-slug <slug>` to resolve the tenant and inject `target_client_id` at publish time.
97
+ - Publish can sign remote metadata headers with `--signing-key` and applies explicit version-conflict policy via `--version-conflict`.
98
+ - Publish release/registry handoff baseline: `--release-channel` and `--registry-target` are carried in signed metadata, payload release envelope, and remote handoff headers.
99
+ - Env/profile support: `XAPPS_CLI_RELEASE_CHANNEL` and `XAPPS_CLI_REGISTRY_TARGET` with precedence `flags > env > profile`.
100
+ - CLI failures expose stable machine-readable `error.code` values (for example `CLI_INVALID_OPTION`, `CLI_REMOTE_LOGS_ERROR`, `CLI_CONFIRM_REQUIRED`).
101
+ - Remote publish outcome contract baseline: `created`, `updated`, `already_exists` (other outcomes fail with `CLI_REMOTE_PUBLISH_ACK_INVALID`).
102
+ - Provider interop baseline: publish ack parser accepts canonical flat or nested (`ack`/`data`/`publish`/`release`) outcome fields and normalizes common aliases (for example `exists` -> `already_exists`).
103
+ - CI behavior: version-conflict in `fail` mode exits with code `3` (`[CLI_VERSION_CONFLICT]`).
104
+ - Logs durable follow/resume contract: `--follow-cursor-file` persists `next_cursor` state and auto-resumes on subsequent runs.
105
+ - Managed logs resume baseline: `lease_id` + `checkpoint` are accepted from remote responses and replayed on next poll/run (via `--follow-cursor-file` or explicit `--lease-id`/`--checkpoint` flags).
106
+ - `context export` emits deterministic JSON context (`schema_version=xapps.context.v1`) for automation/agent workflows.
107
+ - Phase-1 internal preset: `--preset internal-v1` adds canonical refs/spec/test anchors for monorepo workflows.
108
+ - Useful with the first publisher path sample: `apps/publishers/xplace/xapps/xplace-certs/manifest.json`
109
+ - Tunnel contract now includes explicit target-host allowlist enforcement and stable session identity (`--session-id` / `--session-file`) with runtime status endpoint `GET /__status`.
110
+ - Tunnel session lifecycle baseline now supports `--session-policy` (`reuse|require|rotate`) with deterministic conflict/target-mismatch handling for reconnect safety.
111
+ - `dev` v0 includes:
112
+ - manifest watch + revalidation
113
+ - local callback simulation for `/v1/requests/:id/events` and `/v1/requests/:id/complete`
114
+ - dry-run payload inspection
115
+ - internal-repo helper subcommands:
116
+ - `status refs` (prints canonical PM/audit/checklist refs)
117
+ - `check v1` (machine-readable V1 baseline repo-check summary)
118
+ - `check flow --name ...` (predefined flow verification command plans)
119
+ - `check flow --from <flow.json>` (load custom app/team flow definitions; preferred for app-specific workflows)
120
+ - optional `--run` executes the predefined flow command set and returns aggregated result
121
+ - optional `--artifacts-dir` redirects generated flow artifacts (for example `xplace-certs` AI plan/check JSON outputs)
122
+ - `xapps dev check flow init` generates starter JSON flow files so custom app workflows live outside CLI core
123
+ - optional prefill flags reduce edits for real app/workspace flows (`--manifest`, `--policy`, `--smoke-script`, `--flow-id`)
124
+ - `xapps dev check flow lint` validates custom flow shape/command hygiene before running it
125
+ - `ai` Phase-1 internal-mode baseline includes machine-readable plan/check contracts:
126
+ - `ai plan` emits deterministic machine-readable plan contract (`xapps.ai.plan.v1`)
127
+ - mock-aware for JSON Forms (`--mocks-dir` / `--mocks`) and can emit `suggest.manifest_patch` hints for `input_schema` and `input_ui_schema`
128
+ - `--ask-guidance` prompts for a one-line instruction in TTY mode (for example: infer complete fields from mockups, build a step wizard, add supported preview sections, exclude payment screens handled by guards)
129
+ - `--llm` enables OpenAI-compatible manifest suggestions (default model `gpt-5.2`, override with `--llm-model` or `XAPPS_AI_MODEL`)
130
+ - LLM auth/base URL can be provided via `--llm-api-key` / `--llm-base-url` or env (`OPENAI_API_KEY`, `XAPPS_AI_API_KEY`, `OPENAI_BASE_URL`)
131
+ - remote import fetches default to `--fetch-timeout-ms 10000`; LLM calls default to `--llm-timeout-ms 30000` (or env `XAPPS_AI_TIMEOUT_MS`)
132
+ - if LLM is unavailable or returns incomplete image-mock hints, CLI falls back to heuristic suggestions and reports `llm_error`
133
+ - `--apply-manifest-hints` validates and writes suggested manifest patches (optional; review-only usage is supported by default)
134
+ - `ai check` validates plan contract shape in read-only internal mode (`xapps.ai.check.v1`)
135
+ - use `--policy-preset internal-readonly` for quick internal checks
136
+ - use `--policy <file>` for app-specific stricter allowlists (for example `xplace-certs`)
137
+ - `test` baseline validates vectors against manifest schemas and tool names.
138
+ - `publish` baseline creates a local `bundle.json` artifact and can optionally POST it to a remote endpoint (`--publish-url`) for CI/CD handoff, with timeout + retry/backoff controls.
139
+ - Payment provider credential bundle placeholders are supported via repeated `--replace-env` mappings before publish (for example `payment_provider_credentials_refs` placeholders in policy manifests).
140
+ - `logs` baseline reads local publish-bundle history and can optionally query a remote logs endpoint (`--logs-url`) with timeout + retry/backoff controls.
141
+ - `tunnel` baseline is a local relay (not a public ngrok-style tunnel yet) and supports optional inbound token enforcement (`--require-auth-token`), local readiness probe (`/__ready`), upstream timeout handling, and transient retries for idempotent methods.
142
+ - See DX status/checklist: `docs/guides/14-sdk-cli-ai-checklist.md`.
143
+
144
+ ### Profile Config Schema
145
+
146
+ Path: `~/.xapps/config`
147
+
148
+ ```json
149
+ {
150
+ "version": 1,
151
+ "profiles": {
152
+ "default": { "token": "pat_xxx", "apiKey": "xapps_key_xxx" },
153
+ "ci": { "token": "pat_ci_xxx" }
154
+ }
155
+ }
156
+ ```
157
+
158
+ Rules:
159
+
160
+ - `version: 1` is current baseline schema.
161
+ - `profiles` is a map keyed by profile name.
162
+ - Additive schema evolution is expected; unknown keys are ignored.
163
+ - Effective precedence remains `flags > env > profile`.
164
+
165
+ ### Command/Auth Matrix
166
+
167
+ | Command | Remote knobs | Auth/profile | Intended rollout |
168
+ | --------- | ---------------------------------------------------------------------------- | ----------------------------------- | ----------------------------- |
169
+ | `publish` | `--publish-url` + release routing (`--release-channel`, `--registry-target`) | flags/env/profile | CI release handoff |
170
+ | `logs` | `--logs-url` | flags/env/profile | Operator triage follow/resume |
171
+ | `tunnel` | `--target` (+ local relay settings) | profile + inbound auth token policy | Local integration debugging |
172
+
173
+ Adoption policy:
174
+
175
+ 1. Document examples for `publish`, `logs`, and `tunnel` together for operator parity.
176
+ 2. Keep precedence explicit (`flags > env > profile`) in remote examples.
177
+ 3. Use machine-readable codes/exit behavior for CI branching.
178
+
179
+ ## `ai plan` Examples (Mock-Aware / LLM)
180
+
181
+ Review-only heuristic suggestions (no API key):
182
+
183
+ ```bash
184
+ xapps ai plan \
185
+ --mode internal \
186
+ --from ./manifest.json \
187
+ --mocks-dir ./mocks \
188
+ --ask-guidance \
189
+ --json
190
+ ```
191
+
192
+ Review-only LLM suggestions (OpenAI-compatible; default model `gpt-5.2`):
193
+
194
+ ```bash
195
+ export OPENAI_API_KEY=...
196
+ export XAPPS_AI_MODEL=gpt-5.2
197
+ export XAPPS_AI_TIMEOUT_MS=30000
198
+
199
+ xapps ai plan \
200
+ --mode internal \
201
+ --from ./manifest.json \
202
+ --mocks-dir ./mocks \
203
+ --guidance "Infer the complete form fields from these mockups, build a step wizard, add supported widget preview sections, and exclude payment screens because payment is handled by guards." \
204
+ --llm \
205
+ --llm-timeout-ms 30000 \
206
+ --json
207
+ ```
208
+
209
+ Optional provider overrides:
210
+
211
+ ```bash
212
+ xapps ai plan \
213
+ --mode internal \
214
+ --from ./manifest.json \
215
+ --mocks-dir ./mocks \
216
+ --llm \
217
+ --llm-model gpt-5.2 \
218
+ --llm-base-url https://api.openai.com/v1 \
219
+ --llm-api-key "$OPENAI_API_KEY" \
220
+ --json
221
+ ```
222
+
223
+ Optional apply mode (validates manifest before write):
224
+
225
+ ```bash
226
+ xapps ai plan \
227
+ --mode internal \
228
+ --from ./manifest.json \
229
+ --mocks-dir ./mocks \
230
+ --guidance "Infer the complete form fields from these mockups, build a step wizard, add supported widget preview sections, and exclude payment screens because payment is handled by guards." \
231
+ --llm \
232
+ --apply-manifest-hints \
233
+ --json
234
+ ```
235
+
236
+ ## CI Cookbook
237
+
238
+ ### Provider credential bundle placeholders
239
+
240
+ When manifests contain provider credential ref placeholders (for example in
241
+ `payment_provider_credentials_refs`), resolve them at publish time:
242
+
243
+ ```bash
244
+ xapps publish \
245
+ --yes \
246
+ --from ./manifest.json \
247
+ --replace-env __GATEWAY_STRIPE_SECRET_REF__=GATEWAY_STRIPE_SECRET_REF \
248
+ --replace-env __GATEWAY_STRIPE_WEBHOOK_SECRET_REF__=GATEWAY_STRIPE_WEBHOOK_SECRET_REF \
249
+ --replace-env __GATEWAY_PAYPAL_CHECKOUT_BASE_URL_REF__=GATEWAY_PAYPAL_CHECKOUT_BASE_URL_REF
250
+ ```
251
+
252
+ ### 1) Strict release (fail on existing version)
253
+
254
+ ```bash
255
+ xapps publish \
256
+ --yes \
257
+ --from ./manifest.json \
258
+ --publish-url "$PUBLISH_URL" \
259
+ --token "$XAPPS_CLI_TOKEN" \
260
+ --version-conflict fail
261
+ ```
262
+
263
+ Note: publish is tenant-aware. For `--publish-url`, set `target_client_id` in the manifest. For `--publisher-gateway-url`, you can alternatively use `--target-client-slug <tenant-slug>`.
264
+
265
+ Behavior:
266
+
267
+ - Exit `0` on success (`created` or `updated`).
268
+ - Exit `3` on `already_exists` conflict (`[CLI_VERSION_CONFLICT]`).
269
+
270
+ ### 2) Idempotent release (allow existing version)
271
+
272
+ ```bash
273
+ xapps publish \
274
+ --yes \
275
+ --from ./manifest.json \
276
+ --publish-url "$PUBLISH_URL" \
277
+ --token "$XAPPS_CLI_TOKEN" \
278
+ --version-conflict allow
279
+ ```
280
+
281
+ Note: publish is tenant-aware. For `--publish-url`, set `target_client_id` in the manifest. For `--publisher-gateway-url`, you can alternatively use `--target-client-slug <tenant-slug>`.
282
+
283
+ Behavior:
284
+
285
+ - Exit `0` on `created`, `updated`, or `already_exists`.
286
+
287
+ ### 3) Conflict-aware shell flow
288
+
289
+ ```bash
290
+ set +e
291
+ xapps publish --yes --from ./manifest.json --publish-url "$PUBLISH_URL" --version-conflict fail
292
+ status=$?
293
+ set -e
294
+
295
+ if [ "$status" -eq 3 ]; then
296
+ echo "Version already exists, skipping release step."
297
+ elif [ "$status" -ne 0 ]; then
298
+ echo "Publish failed with code $status"
299
+ exit "$status"
300
+ fi
301
+ ```
302
+
303
+ ### 4) Machine-Readable Error Codes
304
+
305
+ | Code | Meaning |
306
+ | ------------------------------------ | ----------------------------------------------------------------------------------- |
307
+ | `CLI_UNKNOWN_COMMAND` | Command is not recognized. |
308
+ | `CLI_INVALID_ARGS` | Required args are missing. |
309
+ | `CLI_INVALID_OPTION` | Option value is invalid. |
310
+ | `CLI_INVALID_JSON` | JSON file/payload parse failure. |
311
+ | `CLI_CONFIG_INVALID` | Profile config file is malformed. |
312
+ | `CLI_PROFILE_NOT_FOUND` | Selected profile is missing in config. |
313
+ | `CLI_CONFIRM_REQUIRED` | `publish` needs confirmation in non-interactive mode (`--yes`). |
314
+ | `CLI_CONFIRM_DECLINED` | Interactive publish confirmation was declined. |
315
+ | `CLI_VERSION_CONFLICT` | Remote publish returned `already_exists` with conflict mode `fail` (exit code `3`). |
316
+ | `CLI_REMOTE_PUBLISH_ERROR` | Remote publish request/response failed. |
317
+ | `CLI_REMOTE_PUBLISH_ACK_INVALID` | Remote publish ack had unsupported outcome contract. |
318
+ | `CLI_REMOTE_LOGS_ERROR` | Remote logs request/response failed. |
319
+ | `CLI_BUNDLE_NOT_FOUND` | Local publish bundle path/directory had no usable entries. |
320
+ | `CLI_CURSOR_STATE_IO` | Cursor state file read/write failure for logs follow-resume. |
321
+ | `CLI_TUNNEL_TARGET_NOT_ALLOWED` | Tunnel target host is outside allowlist policy. |
322
+ | `CLI_TUNNEL_SESSION_IO` | Tunnel session file read/write failure. |
323
+ | `CLI_TUNNEL_SESSION_REQUIRED` | `--session-policy require` used without persisted or explicit session id. |
324
+ | `CLI_TUNNEL_SESSION_CONFLICT` | Explicit `--session-id` conflicts with persisted session identity. |
325
+ | `CLI_TUNNEL_SESSION_TARGET_MISMATCH` | Persisted session target differs from current `--target` under strict policy. |
326
+ | `CLI_RUNTIME_ERROR` | Fallback unexpected runtime error. |
327
+
328
+ ## Operator Cookbook
329
+
330
+ ### Supported tenant/publisher workflow
331
+
332
+ Supported external operator subset:
333
+
334
+ - `xapps init`
335
+ - `xapps import`
336
+ - `xapps validate`
337
+ - `xapps test`
338
+ - `xapps publish`
339
+ - `xapps logs`
340
+ - `xapps publisher endpoint credential set`
341
+ - `xapps publisher endpoint credential ensure`
342
+
343
+ Repo-only helpers (`dev`, `ai`, `context export --preset internal-v1`, `tunnel`) stay available
344
+ but are not part of the supported tenant/publisher publish contract.
345
+
346
+ ### Recommended sequence
347
+
348
+ 1. Create or import a manifest.
349
+ 2. Validate it.
350
+ 3. Run `xapps test` when you have contract vectors.
351
+ 4. Publish locally or to the remote gateway/publish target.
352
+ 5. Ensure endpoint credentials for secured publisher endpoints.
353
+ 6. Use `xapps logs` for local bundle history or remote triage.
354
+
355
+ ### Authoring baseline
356
+
357
+ ```bash
358
+ xapps init --out ./my-xapp
359
+ xapps validate --from ./my-xapp/manifest.json
360
+ ```
361
+
362
+ ### OpenAPI import baseline
363
+
364
+ ```bash
365
+ xapps import --from ./openapi.yaml --out ./manifest.json
366
+ xapps validate --from ./manifest.json
367
+ ```
368
+
369
+ ### A) Local Handoff (no remote services)
370
+
371
+ ```bash
372
+ # 1) Generate and validate
373
+ xapps import --from ./openapi.yaml --out ./manifest.json
374
+ xapps validate --from ./manifest.json
375
+ xapps test --from ./manifest.json --vectors ./vectors.json
376
+
377
+ # 2) Package local artifact
378
+ xapps publish --from ./manifest.json --out ./artifacts/xapps-publish/bundle.json
379
+
380
+ # 3) Inspect local history
381
+ xapps logs --from ./artifacts/xapps-publish/bundle.json --json
382
+ ```
383
+
384
+ Note: local bundle packaging still enforces tenant-aware publish requirements (`target_client_id` in the manifest).
385
+
386
+ ### B) CI Handoff (remote publish)
387
+
388
+ ```bash
389
+ xapps publish \
390
+ --yes \
391
+ --from ./manifest.json \
392
+ --publish-url "$PUBLISH_URL" \
393
+ --token "$XAPPS_CLI_TOKEN" \
394
+ --idempotency-key "$CI_PIPELINE_ID" \
395
+ --version-conflict fail
396
+ ```
397
+
398
+ Use `--version-conflict allow` for idempotent release semantics.
399
+
400
+ ### B.1) Internal Local Gateway Publish (publisher routes)
401
+
402
+ ```bash
403
+ xapps publish \
404
+ --yes \
405
+ --from ./manifest.json \
406
+ --publisher-gateway-url http://localhost:3000 \
407
+ --target-client-slug xconect \
408
+ --api-key "$PUBLISHER_API_KEY"
409
+ ```
410
+
411
+ This uses the gateway publisher API routes (`/publisher/import-manifest` and
412
+ `/publisher/xapp-versions/:id/publish`) and still writes the local `bundle.json` artifact.
413
+ `--target-client-slug` resolves the tenant via `/v1/publisher/clients` and injects `target_client_id` for the publish payload/bundle.
414
+
415
+ ### B.2) Internal Publisher Endpoint Credential Ensure (`PUBLISHER_APP` auth)
416
+
417
+ Preferred normal operator path after publish:
418
+
419
+ ```bash
420
+ export XPLACE_XAPP_INGEST_API_KEY=xplace-dev-api-key
421
+
422
+ xapps publisher endpoint credential ensure \
423
+ --gateway-url http://localhost:3000 \
424
+ --api-key xplace-dev-api-key \
425
+ --xapp-slug xplace-weather-now \
426
+ --env prod \
427
+ --auth-type api-key \
428
+ --header-name x-xplace-api-key \
429
+ --secret-env XPLACE_XAPP_INGEST_API_KEY \
430
+ --json
431
+ ```
432
+
433
+ ### B.3) Internal Publisher Endpoint Credential Setup (`PUBLISHER_APP` auth)
434
+
435
+ Use this after publishing an xapp version to configure the gateway-side endpoint credential
436
+ used for `PUBLISHER_APP` dispatch auth.
437
+
438
+ ```bash
439
+ export XPLACE_XAPP_INGEST_API_KEY=xplace-dev-api-key
440
+
441
+ xapps publisher endpoint credential set \
442
+ --gateway-url http://localhost:3000 \
443
+ --api-key xplace-dev-api-key \
444
+ --xapp-slug xplace-weather-now \
445
+ --env prod \
446
+ --auth-type api-key \
447
+ --header-name x-xplace-api-key \
448
+ --secret-env XPLACE_XAPP_INGEST_API_KEY \
449
+ --json
450
+ ```
451
+
452
+ This stores the endpoint credential in the gateway (not in the manifest). The CLI redacts secret
453
+ material in output and reports only endpoint/credential identifiers and metadata.
454
+
455
+ ### C) Managed Remote Logs Handoff
456
+
457
+ ```bash
458
+ xapps logs \
459
+ --logs-url "$LOGS_URL" \
460
+ --token "$XAPPS_CLI_TOKEN" \
461
+ --follow \
462
+ --follow-cursor-file ./.xapps/log-cursor.json \
463
+ --lease-id "$LOG_LEASE_ID" \
464
+ --checkpoint "$LOG_CHECKPOINT" \
465
+ --severity warn \
466
+ --since "2026-01-01T00:00:00Z"
467
+ ```
468
+
469
+ ### D) Local Tunnel Relay Ops
470
+
471
+ ```bash
472
+ # Start relay with stable identity
473
+ xapps tunnel \
474
+ --target http://127.0.0.1:9999 \
475
+ --listen-port 4041 \
476
+ --session-file ./.xapps/tunnel-session.json \
477
+ --session-policy reuse \
478
+ --allow-target-hosts 127.0.0.1,localhost
479
+
480
+ # Runtime status
481
+ curl http://127.0.0.1:4041/__status
482
+ ```
483
+
484
+ ### Recovery Playbook (deterministic)
485
+
486
+ 1. `CLI_VERSION_CONFLICT` (exit `3`)
487
+ - Keep `fail` in strict release pipelines.
488
+ - Switch to `--version-conflict allow` for idempotent promotion jobs.
489
+ 2. `CLI_REMOTE_PUBLISH_ACK_INVALID`
490
+ - Treat as provider contract drift; do not auto-retry blindly.
491
+ - Capture raw provider response and fail the job.
492
+ 3. `CLI_REMOTE_LOGS_ERROR`
493
+ - Check retryability metadata and remote status.
494
+ - Keep cursor file unchanged when follow loop fails unexpectedly.
495
+ 4. `CLI_CURSOR_STATE_IO`
496
+ - Verify cursor path permissions and parent directory existence.
497
+ - Retry after fixing filesystem state.
498
+ 5. `CLI_TUNNEL_TARGET_NOT_ALLOWED` / `CLI_TUNNEL_SESSION_IO`
499
+ - Update explicit allowlist (`--allow-target-hosts`) or session-file path.
500
+ - Re-run tunnel with corrected policy/path.
501
+
502
+ ### CI Error Handling Pattern
503
+
504
+ ```bash
505
+ set +e
506
+ output="$(xapps publish --yes --from ./manifest.json --publish-url "$PUBLISH_URL" --version-conflict fail 2>&1)"
507
+ status=$?
508
+ set -e
509
+
510
+ if [ "$status" -eq 0 ]; then
511
+ echo "publish_ok"
512
+ elif [ "$status" -eq 3 ] || echo "$output" | grep -q "CLI_VERSION_CONFLICT"; then
513
+ echo "publish_conflict_already_exists"
514
+ exit 0
515
+ elif echo "$output" | grep -q "CLI_REMOTE_PUBLISH_ACK_INVALID"; then
516
+ echo "publish_provider_contract_drift"
517
+ exit 1
518
+ elif echo "$output" | grep -q "CLI_REMOTE_PUBLISH_ERROR"; then
519
+ echo "publish_remote_transport_failure"
520
+ exit 1
521
+ else
522
+ echo "$output"
523
+ exit "$status"
524
+ fi
525
+ ```
526
+
527
+ ## Real-world Flows (Publisher + Tenant)
528
+
529
+ ### 1) Publisher release handoff (conflict-tolerant)
530
+
531
+ ```bash
532
+ xapps publish \
533
+ --yes \
534
+ --from ./manifest.json \
535
+ --publish-url "$PUBLISH_URL" \
536
+ --token "$XAPPS_CLI_TOKEN" \
537
+ --release-channel stable \
538
+ --registry-target tenant-a \
539
+ --version-conflict allow
540
+ ```
541
+
542
+ ### 2) Tenant/operator logs follow resume (multi-run continuity)
543
+
544
+ ```bash
545
+ xapps logs \
546
+ --logs-url "$LOGS_URL" \
547
+ --token "$XAPPS_CLI_TOKEN" \
548
+ --follow \
549
+ --follow-cursor-file ./.xapps/logs.state \
550
+ --severity error
551
+ ```
552
+
553
+ ### 3) Local integration callback debugging (stable tunnel identity)
554
+
555
+ ```bash
556
+ xapps tunnel \
557
+ --target http://127.0.0.1:9999 \
558
+ --session-file ./.xapps/tunnel-session.json \
559
+ --session-policy reuse
560
+ ```