- π€ LLM usage: $1.5000 (10 commits)
- π€ Human dev: ~$1191 (11.9h @ $100/h, 30min dedup)
Generated on 2026-05-13 using openrouter/qwen/qwen3-coder-next
Standalone CQL (Cognitive Query Language) editor and scenario visualization
tool. Designed to be embedded inside the maskservice frontend at
/connect-scenario/scenarios via an <iframe>, while remaining independently
runnable at http://cql.localhost/connect-scenario/scenarios.
/connect-scenario/scenarios?font=default&theme=dark&role=admin&lang=pl&size=1280&scenario=ts-c20
| Param | Allowed values | Effect |
|---|---|---|
font |
default, mono, dyslexic, large |
Swaps --font-display / --font-base-size on :root |
theme |
dark, light, high-contrast |
Swaps the palette via :root[data-theme=β¦] CSS |
role |
admin, operator, viewer, guest |
viewer/guest are read-only β buttons/tabs are disabled |
lang |
pl, en, de |
Forces the i18n dictionary (overrides localStorage / navigator) |
size |
320β¦4096 | Sets .dash-content max-width via --viewport-size |
scenario |
any scenario id (e.g. ts-c20) |
Triggers ScenariosApi.get(id) + WS ScenarioUpdated subscription |
Additional tracking params (goal, step, status) are preserved by the
Scenarios page so the parent frame can observe execution state.
- Node.js 18+
- npm 9+
- Docker + Docker Compose (for containerized deployment)
# Install dependencies
npm install
# Start dev server
npm run dev
# β http://localhost:3001/connect-scenario/scenarios?scenario=ts-c20# Production build (outputs to dist/)
npm run build
# Or use Makefile
make build| Command | Description |
|---|---|
make help |
Show all available commands |
make install |
Install npm dependencies |
make dev |
Start Vite dev server on port 3001 |
make dev-docker |
Restart Docker stack (down + up + build) |
make dev-open |
Start Docker containers and show URLs |
make build |
Build production bundle |
make clean |
Remove dist/ directory |
The image uses nginx:alpine with envsubst rendering nginx.conf.template
at container start. The template proxies /api/* β BACKEND_API_URL and
/ws β BACKEND_WS_URL, so the React app can simply call fetch('/api/β¦')
and new WebSocket('/ws') regardless of where maskservice runs.
# Full docker-compose stack with Traefik on cql.localhost
make dev-docker
# Or standalone
docker build -t oqlos-cql:latest .
docker run -p 8091:80 \
-e BACKEND_API_URL=http://host.docker.internal:8080 \
-e BACKEND_WS_URL=http://host.docker.internal:8080 \
-e FRAME_ANCESTORS="'self' http://*.localhost" \
oqlos-cql:latestCopy .env.example to .env and adjust:
| Variable | Default | Description |
|---|---|---|
| Development | ||
VITE_CQL_PORT |
3001 |
Vite dev server port |
VITE_API_PROXY_TARGET |
http://localhost:8080 |
Backend API proxy target (dev) |
VITE_WS_PROXY_TARGET |
ws://localhost:8080 |
WebSocket proxy target (dev) |
| Docker | ||
DOCKER_DOMAIN_CQL |
cql.localhost |
Main domain for CQL editor |
DOCKER_DOMAIN_TRAEFIK_CQL |
traefik.cql.localhost |
Traefik dashboard domain |
VITE_CQL_HTTP_PORT |
8092 |
Host port for HTTP (maps to container 80) |
VITE_CQL_TRAEFIK_PORT |
8093 |
Host port for Traefik dashboard (maps to 8080) |
| Runtime | ||
BACKEND_API_URL |
http://host.docker.internal:8080 |
Where nginx proxies /api/* |
BACKEND_WS_URL |
http://host.docker.internal:8080 |
Where nginx proxies /ws |
FRAME_ANCESTORS |
'self' http://*.localhost |
CSP frame-ancestors for iframe embed |
maskservice/c2004/frontend/src/pages/connect-scenario-scenarios.page.tshas been simplified to render an<iframe src="β¦cql.localhostβ¦">and forward the current querystring. Its previous implementation is archived next to it as.bak.- Every other maskservice route that touches the DSL (
dsl-editor,library-editor,func-editor,map-editor, CQRS handlers) is untouched so the rest of the system keeps compiling. - The TypeScript DSL source from maskservice was copied verbatim into
legacy/in this repo as reference material β seelegacy/README.mdfor the origin map. It is not part of the Vite build (vite.config.jsdenies the path and.dockerignoreexcludes it from the image context).
ββββββββββββββββββββββββββββββ HTTP /api/v3/data/test_scenarios
β maskservice frontend β ββββββββββββββββββββββββββββββββββββββββββ
β /connect-scenario/scenariosβ β
β <iframe> β βΌ
ββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββββββ
β iframe src β cql container (React + Vite β nginx) β
βββββββββββββββββββΊ β /connect-scenario/scenarios β
β ββ fetch('/api/β¦') β proxy β backend β
β ββ WebSocket('/ws') β proxy β backend β
ββββββββββββββββββββββββββββββββββββββββββββ
β
HTTP + WS β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββ
β maskservice backend (host or container) β
ββββββββββββββββββββββββββββββββββββββββββββ
- OQL / iQL syntax highlighting
- Visual scenario editor (
OqlStepRenderer) - Terminal simulation
- Report viewer (
data.json) - Real-time WS connection indicator
- Role-based read-only mode
- Themeable (
dark/light/high-contrast) - Polish / English / German i18n
# Find process using port 3001
lsof -i :3001
# Kill it
kill -9 <PID>Add to /etc/hosts:
echo '127.0.0.1 cql.localhost traefik.cql.localhost' | sudo tee -a /etc/hostsCheck BACKEND_API_URL points to reachable backend:
- Backend on host:
http://host.docker.internal:8080 - Backend in container:
http://maskservice-api:8080(same network)
Verify FRAME_ANCESTORS includes parent domain:
FRAME_ANCESTORS='self' http://*.localhost https://*.localhostEnsure VITE_WS_PROXY_TARGET uses ws:// or wss:// protocol, not http://.
Licensed under Apache-2.0.