# Architecture ## Two components ### 1. `nextcloud-node-red` (Docker + nodes) A thin wrapper around the official [`nodered/node-red`](https://hub.docker.com/r/nodered/node-red) image: 1. **Build time:** `nodes/nextcloud-ocs/` is copied to `/opt/nextcloud-nodes/node-red-contrib-nextcloud-ocs`. 2. **Run time:** `entrypoint.sh` runs as container `ENTRYPOINT`, copies that tree into `/data/node_modules/node-red-contrib-nextcloud-ocs`, then starts `node-red --userDir /data`. Node-RED discovers contrib nodes from `{userDir}/node_modules/*/package.json` → `node-red.nodes` map. ### 2. `nodered-embed` (Nextcloud app) PHP app registered as `nodered_embed`: - **Navigation** entry opens a full-page iframe to the configured Node-RED URL. - **CSPListener** relaxes Content-Security-Policy so Nextcloud may embed Node-RED (`frame-src`) and Node-RED may embed Nextcloud pages if needed (`frame-ancestors`). - **Admin settings** store `nodered_url`, optional Docker container name, and a Docker-management flag (UI only for now). ## Node implementation pattern Each functional node follows the same structure: ``` collectives.js → OPERATIONS hash (operationId → method, path, body fields) collectives.html → Editor UI, dropdown of operations, config node picker nextcloud-config.js → Credential node (baseUrl, username, password) ``` On input: 1. Resolve `msg.operation` or the configured default operation. 2. Substitute path placeholders (`{id}`, `{collectiveId}`, …) from config + `msg.*`. 3. Build query string and JSON body from configured fields + `msg` overrides. 4. HTTP request with `OCS-APIRequest: true`, `Accept: application/json`, Basic Auth. 5. Parse JSON into `msg.payload`, set `msg.statusCode`, `node.send(msg)`. **ocs-api** is the escape hatch: you supply any OCS path and method without adding a new operation to the hash. ## Data persistence | Path | Contents | |------|----------| | `/data/flows.json` | Flows (Docker volume `node-red-data`) | | `/data/flows_cred.json` | Encrypted credentials | | `/data/node_modules/node-red-contrib-nextcloud-ocs/` | Copy of custom nodes (refreshed on each start) | The named volume **masks** anything copied into `/data` at image build time. That is why the entrypoint always re-copies from `/opt`. ## Network ``` Node-RED container (--network host) → https://cloud.example.com (same host or LAN) ``` On Ubuntu, a bridge network often breaks `localhost` / hostname resolution (`127.0.1.1` in `/etc/hosts`). Host networking avoids that for co-located Nextcloud + Node-RED. ## Authentication flow ``` Editor: nextcloud-config node → stored in flows_cred.json (encrypted) Runtime: each API node → RED.nodes.getNode(config.nextcloud) → credentials.username + credentials.password → Authorization: Basic base64(user:app-password) ``` Use **app passwords**, not the account login password. ## Versioning Package version in `nodes/nextcloud-ocs/package.json` (e.g. `0.8.0`) should be bumped when adding nodes or breaking operation ids. After deploy, verify inside the container: ```bash docker exec nextcloud-node-red cat /data/node_modules/node-red-contrib-nextcloud-ocs/package.json ```