ai-chatbot/docs/pascal-editor-integration.md

128 lines
4.5 KiB
Markdown

# Pascal Editor Integration
## Current Shape
The app now exposes a first-phase Pascal Editor workspace at `/pascal-editor`.
It is intentionally iframe-based so Pascal can be self-hosted as a standalone
Next app without forcing its unpublished `@pascal-app/nodes` workspace package
into the main application dependency graph.
The wrapper route is protected by the host application's existing login system.
Unauthenticated users are redirected to `/login?callbackUrl=/pascal-editor`.
The embedded Pascal app is self-hosted and does not use Pascal's official hosted
sign-in flow.
The page resolves the editor source in this order:
1. `NEXT_PUBLIC_PASCAL_EDITOR_URL`
2. `PASCAL_EDITOR_URL`
3. `/vendor/pascal-editor/index.html` when that file exists
4. `http://localhost:3002` when that self-hosted Pascal service is reachable in
local development
If none is available, the page shows an explicit configuration state instead of
loading a broken iframe.
## Why Iframe First
`@pascal-app/core`, `@pascal-app/viewer`, and `@pascal-app/editor` are published
on npm, but the official standalone app still depends on `@pascal-app/nodes`
from its monorepo workspace. That package registers the built-in node
definitions used by walls, doors, windows, levels, roofs, stairs, and other
editable building elements. Until it is published or vendored, a pure npm-based
native React integration would be incomplete.
## Deployment Options
### Local Self-Hosted Dev Service
Run Pascal Editor as a local standalone service:
```bash
pnpm pascal:dev
```
The helper clones `pascalorg/editor` into the ignored `.pascal-editor/`
directory on first run, installs its dependencies, and starts `apps/editor` on
`http://localhost:3002`.
Then open:
```text
http://localhost:3000/pascal-editor
```
The host app auto-detects `http://localhost:3002` in development, so no env var
is required for the default local setup.
### Same-Origin Static Bundle
Build Pascal Editor as a static bundle and place it here:
```text
public/vendor/pascal-editor/index.html
```
Then leave `NEXT_PUBLIC_PASCAL_EDITOR_URL` empty or set it explicitly:
```env
NEXT_PUBLIC_PASCAL_EDITOR_URL=/vendor/pascal-editor/index.html
```
### Separate Pascal Service
Run Pascal Editor as its own service, then set:
```env
NEXT_PUBLIC_PASCAL_EDITOR_URL=https://pascal-editor.example.com
```
`next.config.ts` reads this value and allows that origin in `frame-src` so the
iframe is not blocked by our Content Security Policy.
`PASCAL_EDITOR_URL` is also supported for server-side configuration. The final
iframe URL is visible to the browser either way, so do not place secrets in it.
The integration no longer falls back to `editor.pascal.app`, because the
official hosted app can require Pascal sign-in for create, fork, and save
actions. Use a local or self-hosted Pascal service for an auth-independent POC.
Keep any separately deployed Pascal service behind the same private network,
reverse proxy, or SSO boundary if direct access to that service must also be
restricted.
### Same-domain authenticated service
The production integration can expose Pascal below `/pascal-service` while the
service itself only listens on a loopback port. Configure:
```env
PASCAL_EDITOR_URL=/pascal-service/scenes
PASCAL_PROXY_SECRET=replace_with_a_long_random_value
```
Nginx must use `auth_request` against `/api/internal/pascal/access`, strip any
client-supplied Pascal identity or secret headers, and inject the authenticated
`X-Pascal-User-Id` into the upstream request. The Pascal scene store uses that
id as `ownerId`, so scene listing and every scene mutation remain user-scoped.
The reviewed configuration is kept in
`deploy/nginx/pascal-service.conf.template`; render its secret placeholder and
include it inside the main HTTPS `server` block.
The private Pascal service points its OpenAI-compatible model base URL to
`/api/internal/pascal-agent/v1` on this application and authenticates with
`PASCAL_PROXY_SECRET`. That gateway resolves the current enabled Agent model
and provider from system settings on every request. OpenAI-compatible
`openai`, `custom`, `alibaba`, and `zhipu` providers work without copying their
API keys into the Pascal service.
## Next Step
After the iframe POC is stable, the native integration path is:
1. Pin a Pascal upstream commit.
2. Vendor or workspace-link `packages/nodes` as `@pascal-app/nodes`.
3. Add Pascal packages to `transpilePackages`.
4. Upgrade `three` to the Pascal-compatible `^0.184` line and retest existing
3D/CAD surfaces.
5. Wire `Editor` `onLoad` / `onSave` to our project storage APIs.