Artur Mukhamadiev 77768ba3ca credentials: offer the approved Confluence origin as a fixed choice
The origin check is an exact match including the context path, so users had
to type "https://collab.lge.com/main" precisely. GET /api/v1/config now
returns the approved origins in canonical form (non-secret: they are the only
destinations the backend will talk to), and the UI swaps the URL text field
for a select listing them, keeping the element id, focus handling and the
Test connection flow unchanged. The text field remains the fallback when the
fetch fails. Backend validation of the submitted URL is untouched. Mock server
serves the endpoint; contract, API and e2e tests cover it.
2026-09-15 15:24:17 +03:00
2026-09-14 17:06:32 +03:00

Confluence Research Web UI

A minimalist web UI that researches a Confluence Data Center instance with a pi agent running in a fresh, network-less rootless Docker container per query, and returns a cited Markdown answer plus optional files the agent produced. Each component documents its own interface in agent/README.md, backend/README.md and frontend/README.md.

The repository also contains the original standalone Confluence crawler, which is unchanged.

Components

Directory Role Developer guide
backend/ FastAPI service: credentials in memory, Confluence/model upstreams, authoritative tool history, container lifecycle, artifact downloads, serves the frontend backend/README.md
agent/ Container image: pinned pi SDK bridge, Python supervisor, local tools, artifact exporter agent/README.md
frontend/ Static UI (vendored marked, DOMPurify and thinking-orbs engine), same-origin mock server for UI development frontend/README.md
tests/integration/ Integration-stage tests connecting the real components this file
deploy/, scripts/, Makefile Deployment configuration and entry points this file

Requirements

  • Linux with a rootless Docker daemon (cgroup v2, memory/CPU/PID limits enforced). docker info must list rootless under Security Options.
  • Python 3.12+ in .venv (verified with 3.14.7), Node 22+ (verified with 26.7) and npm.
  • An OpenAI-compatible Chat Completions endpoint the backend can reach (key held by the backend only).
  • Network access from the backend host to the approved Confluence origin, optionally through a SOCKS5/HTTP proxy.
  • For browser checks: Google Chrome with --remote-debugging-port=9444.

Setup

python3 -m venv .venv && .venv/bin/python -m pip install -r requirements.txt
make install                 # also installs agent/ and frontend/ dev dependencies
make build-image             # builds confluence-pi-agent:rev1 and prints its image ID
cp deploy/confluence-web.env.example deploy/confluence-web.env   # then edit

deploy/confluence-web.env is git-ignored. Every variable is documented in the example file and in backend/README.md. Pin CONFLUENCE_WEB_RUNTIME_IMAGE to the image ID printed by make build-image for an exact runtime, set a deployment-unique CONFLUENCE_WEB_CONTAINER_LABEL_VALUE, and list only approved Confluence origins.

Run

make run                     # scripts/run-backend.sh deploy/confluence-web.env

The backend binds 127.0.0.1:8000 by default and serves the UI at http://127.0.0.1:8000/. Open it in a browser, click the key icon, pick the Confluence origin (the list comes from CONFLUENCE_WEB_APPROVED_ORIGINS, each entry including its context path, for example https://collab.lge.com/main), enter your personal access token (PAT), test the connection, then ask a question. On instances that allow anonymous REST reads, "Test connection" proves the destination is reachable but cannot prove the PAT is valid; a wrong token then shows up as denied or missing pages. Credentials live only in browser memory and in the backend for the duration of a request; a page reload clears them.

Version 1 is a small-team deployment: one backend worker, one query at a time (a second query gets busy), loopback by default. The application has no login of its own; anyone who can reach the port can run queries with their own PAT. Never bind it to a network interface over plain HTTP, because every request carries the user's PAT. If you put a reverse proxy in front, it must accept 6*16 MiB + 64 KiB request bodies, pass client aborts through promptly, avoid buffering bodies to disk, and allow at least 200 s per request.

Serving colleagues on an internal network (IP only, TLS)

Uvicorn terminates TLS itself; no reverse proxy or DNS name is needed. The certificate comes from a private CA that is name-constrained to the listed IP addresses, so colleagues who import it are trusting it for those addresses only. A certificate issued by the same CA for any hostname or any other address is rejected by browsers and by OpenSSL (permitted subtree violation).

make tls IP=172.26.10.20          # creates deploy/tls/{ca,server}.{key,crt}; git-ignored

Then in deploy/confluence-web.env:

CONFLUENCE_WEB_BIND_HOST=172.26.10.20
CONFLUENCE_WEB_TLS_CERT=./deploy/tls/server.crt
CONFLUENCE_WEB_TLS_KEY=./deploy/tls/server.key

Restart with make run and open https://172.26.10.20:8000/. Under HTTPS the session cookie gains the Secure flag automatically and the same-origin check expects https:// origins.

Hand colleagues only deploy/tls/ca.crt, imported once as a trusted root (Windows: double-click, "Trusted Root Certification Authorities"; macOS: Keychain Access; Chrome on Linux: chrome://settings/certificates; Firefox: Settings, Certificates, Authorities). They can read the constraint themselves in the certificate details ("Name Constraints: Permitted IP ..."). Keep ca.key and server.key on the server host. The server certificate is valid for 825 days (the browser maximum); rotate it with the same CA by deleting deploy/tls/server.* and re-running make tls with the CA files kept, or rotate everything by deleting the directory.

Network-free UI development against explicit fakes (no Docker, PAT dev-pat, URL https://approved.example.com):

make run-dev

Credentials, expiry and limits

  • Confluence PAT: entered in the browser per session, sent only to the backend over the same origin, never stored, logged, or passed to the container. The token inherits your Confluence permissions.
  • Model key: backend environment only (CONFLUENCE_WEB_MODEL_API_KEY). For a local llama.cpp server any placeholder works.
  • Session cookie cw_session: HttpOnly, SameSite=Strict, marks artifact ownership only. It is not authentication.
  • Artifacts: at most 20 files, 10 MiB each, 50 MiB per query, 500 MiB total; downloadable for 15 minutes after a successful query, then deleted. Failed or cancelled queries keep nothing.
  • Query: 180 s total deadline by default (CONFLUENCE_WEB_QUERY_TIMEOUT_SECONDS, up to CONFLUENCE_WEB_MAX_DEADLINE_SECONDS, default 900 s) plus 10 s cleanup, prompt up to 16 MiB, answer up to 128 MiB, 100 Confluence calls and 50 model calls per query by default (CONFLUENCE_WEB_MAX_CONFLUENCE_CALLS, CONFLUENCE_WEB_MAX_MODEL_CALLS), container limited to 1 GiB RAM, 1 CPU, 128 processes, no network.
  • Model tokens: CONFLUENCE_WEB_MODEL_CONTEXT_WINDOW_TOKENS and ..._MAX_OUTPUT_TOKENS describe the provider; they are independent of the byte limits above. Large pages or answers can exceed the model's context before the application limits; the UI then shows model_context_exceeded or model_output_limit.

Checks

Command What it runs Needs
make check Crawler + backend + integration (no Docker) pytest, agent host tests, frontend unit/contract tests nothing external
make check-docker Backend real-Docker checks, backend + real runtime image + scripted peers, real provider adapter + runtime, runtime image/isolation/boundary checks rootless Docker, built images
make check-browser Real Chrome against the real backend (scripted runtime), frontend's own e2e suite Chrome on 127.0.0.1:9444, Node

Each subsystem's own commands are documented in its guide and can be run independently:

CONFLUENCE_PAT=synthetic-token-no-network CONFLUENCE_URL=https://approved.example.com .venv/bin/python -m pytest tests/backend
npm --prefix agent test && npm --prefix agent run proof
npm --prefix frontend test && npm --prefix frontend run test:e2e

Fake modes (CONFLUENCE_WEB_DEV_MODE, the backend fake image, the frontend mock server, the runtime's fake backend peer) are explicit opt-ins and never activate on a production failure.

Standalone crawler

Crawls Confluence Data Center pages into Markdown files using a PAT from .env (CONFLUENCE_URL, CONFLUENCE_PAT; see .env.example). PATs require Confluence Data Center / Server 7.9+.

python main.py --space KEY --out output/KEY   # one space
python main.py --all --out output             # all visible spaces
pytest -m live                                # live crawler tests (uses .env)

Each page becomes output/<space>/<page_id>_<slug>.md with YAML front matter. The web backend imports only the crawler's pure conversion functions; it never reads .env.

Description
No description provided
Readme 548 KiB
Languages
Python 52%
JavaScript 26.9%
TypeScript 15.3%
CSS 3.2%
HTML 1.1%
Other 1.5%