Skip to content

DISCO-154: Add SDK Preview Command - #444

Merged
Philipp Koytek (philippkoytek) merged 14 commits into
mainfrom
feature/DISCO-154-sdk-preview
Nov 2, 2026
Merged

Philipp Koytek (philippkoytek) merged 14 commits into
mainfrom
feature/DISCO-154-sdk-preview

Conversation

@philippkoytek

@philippkoytek Philipp Koytek (philippkoytek) commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Description

Adds content-cli sdk preview [--target http://localhost:4200] [--port 4300] [--allow-inline-scripts], a long-running local HTTPS proxy that serves a custom app's dev server to the Codespace Local preview (https://localhost:4300). Developers no longer configure HTTPS, CORS or a CSP meta tag on their own dev server, and the preview blocks inline scripts by default, matching published apps.

  • Proxy (preview-proxy.ts, Node built-ins only): listens on localhost only and forwards every request and WebSocket upgrade to --target. It strips the target's CSP, report-only CSP, X-Frame-Options and CORS headers, then sets the local preview headers. When the target is down it answers 502 with a readable message, logs one warning, and recovers when the target is back. A busy port gives a clear error.
  • Headers (preview-headers.ts): a verbatim copy of localPreviewHeaders() from ems-frontend (libs/common/fragments/sandbox/src/lib/policy.ts). That is the fragment gateway's sandbox policy with 'self' sources and frame-ancestors https://*.celonis.cloud http://localhost:*. A spec in ems-frontend pins the object and fails when the gateway policy drifts.
  • Inline scripts (preview-inline-scripts.ts): blocked by default to match published apps. Some dev servers inject inline scripts required for development, such as React Fast Refresh's preamble. --allow-inline-scripts permits them during local development by adding per-script SHA-256 hashes to the HTML response's script-src, computed from the script text with browser-style line-ending normalization. Both modes warn once per distinct script, explaining whether it is blocked or allowed. Move inline scripts of your own into separate files before publishing.
  • Certificate (preview-certificate.ts): a self-signed localhost certificate (EC P-256; SANs localhost, 127.0.0.1, ::1) from selfsigned@5.5.0, the one new dependency. It is stored in ~/.celonis-content-cli-preview, reused, and regenerated when missing, corrupt or expiring. The system trust store is never touched.
  • Command (sdk-preview.service.ts, module.ts): beta, needs no profile, validates --target (an http(s) origin) and --port, prints the URL and what to do about the certificate, and stops on Ctrl+C. Docs are in docs/user-guide/sdk-commands.md and docs/command-graph.html.

Hot reload stays blocked (connect-src 'none') on purpose, to match production; developers reload the preview instead.

Relevant links

Screen.Recording.2026-10-27.at.17.43.54.mov

Checklist

  • I have self-reviewed this PR
  • I have tested the change and proved that it works in different scenarios: unit tests pass (702), the built CLI was run against a plain Node server and a React + Vite 8 app, and the React app renders through the proxy in headless Chromium. The build and all current CI checks pass. Verification in a tenant Codespace is still open.
  • I have updated docs if needed

Co-Authored-By: Claude noreply@anthropic.com
Includes-AI-Code: true

Co-Authored-By: Claude <noreply@anthropic.com>
Includes-AI-Code: true
Co-Authored-By: Claude <noreply@anthropic.com>
Includes-AI-Code: true
Co-Authored-By: Claude <noreply@anthropic.com>
Includes-AI-Code: true
Co-Authored-By: Claude <noreply@anthropic.com>
Includes-AI-Code: true
Co-Authored-By: Claude <noreply@anthropic.com>
Includes-AI-Code: true
…ine-scripts

The preview now blocks inline scripts by default, like published apps, and warns
about each one with a hint to pass --allow-inline-scripts.

Co-Authored-By: Claude <noreply@anthropic.com>
Includes-AI-Code: true
Co-Authored-By: Claude <noreply@anthropic.com>
Includes-AI-Code: true
Moves the proxy's close() out of the listen callback, uses Sets for the loopback hostnames and bodiless statuses, parses --port without a nested ternary, and asserts that the disconnect test's target request closes.

Co-Authored-By: Claude <noreply@anthropic.com>
Includes-AI-Code: true
@datadog-celonis

datadog-celonis Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Pipelines

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: f0fb1f1 | Docs | Give us feedback!

Comment thread src/commands/sdk/module.ts Resolved
Comment thread src/commands/sdk/module.ts Resolved
Comment thread src/commands/sdk/module.ts Resolved
Comment thread src/commands/sdk/module.ts Resolved
Comment thread src/commands/sdk/preview-proxy.ts Resolved
Comment thread src/commands/sdk/sdk-preview.service.ts Resolved
Comment thread src/commands/sdk/preview-proxy.ts Resolved
Comment thread src/commands/sdk/preview-proxy.ts Resolved
Co-authored-by: Patrick Tamunjoh <38542007+patricktamunjoh@users.noreply.github.com>
@sonarqubecloud

Copy link
Copy Markdown

@philippkoytek
Philipp Koytek (philippkoytek) merged commit 5ea026c into main Nov 2, 2026
5 checks passed
@philippkoytek
Philipp Koytek (philippkoytek) deleted the feature/DISCO-154-sdk-preview branch November 2, 2026 09:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants