# FedWiki Integration This document describes how the member-console integrates with FedWiki for wiki site provisioning and management. ## Architecture Overview The member-console manages FedWiki sites through the **FarmManager API**, a plugin that runs on a designated admin wiki site within a FedWiki farm. The security layer uses a composable architecture that separates authentication from authorization. ### Components | Component | Package | Role | |-----------|---------|------| | Security layer | `wiki-security-composable` | Composable security plugin that separates authentication from authorization. Allows mixing auth providers with authorization enhancers. | | Authentication | `wiki-security-passportjs` | OAuth2/OIDC authentication via Keycloak. Configured per wiki domain in `config.json` under `wikiDomains`. | | Authorization | `wiki-plugin-useraccesstokens` | Adds API token (Bearer) authentication. Tokens are stored per-site in `status/user-access-tokens.json`. | | Farm management | `wiki-plugin-farmmanager` | REST API for programmatic farm management (create, list, delete sites). Requires admin authentication. | ### How FarmManager Works FarmManager is a **site-level plugin with farm-level scope**. It loads per-site (standard FedWiki plugin architecture), but manages all sites in the farm by resolving the parent farm directory from the current site's data path. In practice, one site is designated as the **admin site** (e.g., `admin.localtest.me`). All farm management API calls go through this site. The plugin uses `app.securityhandler.isAdmin(req)` middleware to restrict access to farm admins. ## FarmManager API All endpoints are served from the admin site and require admin authentication via Bearer token. Base URL: `http://admin.localtest.me` (local dev) | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/plugin/farmmanager/sites` | List all wiki sites in the farm | | `POST` | `/plugin/farmmanager/sites` | Create a new wiki site | | `GET` | `/plugin/farmmanager/sites/:domain` | Get details for a single site | | `PATCH` | `/plugin/farmmanager/sites/:domain` | Partially update a site's properties | | `DELETE` | `/plugin/farmmanager/sites/:domain` | Soft-delete (deactivate) a site | | `DELETE` | `/plugin/farmmanager/sites/:domain?hard=true` | Permanently delete a site | ### Authentication The member-console authenticates to the FarmManager API using a **User Access Token** (prefix: `fwuat-`), sent as a Bearer token in the `Authorization` header. Tokens are generated by `wiki-plugin-useraccesstokens` and stored as bcrypt hashes in the admin site's `status/user-access-tokens.json`. Each token has: - A `name` (unique per site) - A `user` (the owner's OAuth2 identity) - A `tokenHash` (bcrypt hash of the token) - A `displayHint` (last 4 characters, for identification) - Optional `scopes` (`site:read`, `site:write`) ## Member-Console Configuration Relevant settings in `mc-config.yaml`: ```yaml # URL of the admin wiki site (where FarmManager plugin is loaded) fedwiki-farm-api-url: "http://admin.localtest.me" # Domains where wiki sites can be created fedwiki-allowed-domains: - "localtest.me" # URL scheme for generated site links fedwiki-site-scheme: "http" # User Access Token for FarmManager API authentication fedwiki-admin-token: "fwuat-6R-p8TMlBBrwH7bV8l5oqsdoSbij5-SFHS5oVRJzGGM" ``` The `FarmManagerClient` in `internal/workflows/fedwiki/farmmanager_client.go` constructs API URLs as `baseURL + path` (e.g., `http://admin.localtest.me/plugin/farmmanager/sites`). ## Local Development Setup ### FedWiki Farm Structure The FedWiki farm runs in Docker (see `test/compose.yaml`) on port 80 with these key directories: ``` test/data/fedwiki/ # Runtime data (mounted as /home/node/.wiki) config.json # Farm configuration (OAuth2, wikiDomains, admin identity) admin.localtest.me/ # Admin site (FarmManager API host) status/ owner.json # Site owner identity (OAuth2 subject) user-access-tokens.json # API tokens for Bearer auth localtest.me/ # Root farm site .localtest.me/ # User-created wiki sites ``` ### Seed Data Seed data lives in `test/seed/fedwiki/` and is copied to `test/data/fedwiki/` on `docker compose up` via the `fedwiki-init` container (`cp -rn`, no-clobber). The seed includes: - `admin.localtest.me/status/owner.json` — Admin site owner (alice, pinned ID: `a0000001-0000-4000-a000-000000000001`) - `admin.localtest.me/status/user-access-tokens.json` — Pre-configured API token for member-console ### config.json The `config.json` is **not seeded** — it is runtime-generated by FedWiki on first boot, or must be manually created. It contains: - `admin` — Farm admin identity (OAuth2 subject). Must match a Keycloak user. - `farm: true` — Enables farm mode. - `wikiDomains` — Per-domain OAuth2 configuration (client ID/secret, Keycloak endpoints). - `security_type`, `auth_provider`, `authz_enhancers` — Composable security stack. If `config.json` is lost, FedWiki will generate a default one on startup, but you'll need to re-configure the OAuth2 wikiDomains and admin identity. ### Keycloak User IDs Test user IDs are **pinned** in `test/seed/keycloak/seed-keycloak.sh` so that FedWiki seed data (owner.json, config.json) can reference them deterministically: | User | ID | Role | |------|----|------| | alice | `a0000001-0000-4000-a000-000000000001` | Operator, FedWiki farm admin | | bob | `b0000002-0000-4000-a000-000000000002` | Member | | carlos | `c0000003-0000-4000-a000-000000000003` | Member | | diana | `d0000004-0000-4000-a000-000000000004` | Member | The Keycloak bootstrap `admin` user ID is assigned by Keycloak and is not pinned. ### Common Issues **"Requested Wiki Does Not Exist" from FarmManager API** - The admin site directory doesn't exist in `test/data/fedwiki/`. Ensure `admin.localtest.me/` exists with at least `status/owner.json`. - Fix: Remove `test/data/fedwiki/` and restart docker compose to re-seed. **EACCES permission denied** - The FedWiki container runs as `node`. If the data directory is owned by root (e.g., after Docker recreates it), FedWiki can't write to it. - Fix: `chmod -R 777 test/data/fedwiki/` or ensure your user UID matches the container's `node` user. **Owner mismatch after Keycloak re-seed** - If Keycloak user IDs change, the OAuth2 `id` in FedWiki's `owner.json` and `config.json` won't match. User IDs are now pinned to prevent this. ## Plugin Source Code - [wiki-security-composable](https://git.coopcloud.tech/wiki-cafe/wiki-security-composable) - [wiki-plugin-farmmanager](https://git.coopcloud.tech/wiki-cafe/wiki-plugin-farmmanager) - [wiki-plugin-useraccesstokens](https://git.coopcloud.tech/wiki-cafe/wiki-plugin-useraccesstokens)