# MAS Integration Research & Plan

## Objectives
- Understand what the Matrix Authentication Service (MAS) needs to replace or augment in the Cloudron Synapse package.
- Capture upstream recommendations for deployment (domains, reverse proxy, database, config) and map them to Cloudron-specific constraints (single app bundle, OpenID provider, Element compatibility).
- Document the next steps to get from the working Synapse package to a MAS-enabled deployment that keeps Element/Element X happy.

## Upstream MAS requirements (source: https://element-hq.github.io/matrix-authentication-service/setup/)
1. **Dedicated authentication service**: MAS runs on its own domain (e.g. `auth.example.com`) and handles account/session management via OIDC. The homeserver (Synapse) becomes an OIDC relying party.
2. **Assets & binaries**: Upstream shipped packages bundle `mas-cli`, the frontend assets, policy wasm, templates, translations, etc. These can be overridden via configuration (paths configurable).
3. **Database**: MAS maintains its own PostgreSQL database with user/session/registration information. Upstream provides `mas-cli database migrate` to manage schema.
4. **Homeserver configuration**: Synapse needs to be configured to trust MAS—this includes replacing the `MXID_LOCALPART_REGEXP`, `oidc_config`, and adjusting `User Interactive Auth` settings to redirect to MAS endpoints.
5. **Reverse proxy**: Both MAS and Synapse must be exposed through a reverse proxy (or Cloudron routing layer) so they can talk over HTTPS. OIDC discovery endpoints must be reachable at sensible URLs.
6. **SSO / upstream provider**: MAS is configurable to use external SSO providers (email, identity providers) but for Cloudron we expect MAS to hook into Cloudron's OpenID provider layer (since Cloudron exposes apps via OpenID for dashboard login).
7. **CLI tooling**: `mas-cli` ships a `config`, `database`, `manage`, `server`, `syn2mas`, `worker`, `templates`, `doctor` command suite. We'll likely rely on the `template` assets and the `doctor` check when packaging.
8. **Templates & policies**: The frontend, policy engine (OPA), and default templates drive what flows look like; for Cloudron we should ensure these assets are present and configurable by the package (perhaps via volume mounts or extraction during install).

## Cloudron-specific considerations
- **Single-app package**: Currently the Cloudron Synapse package bundles Synapse (homeserver) and exposes it via `matrix.example.com`. MAS needs a separate service but Cloudron apps normally run in a single container. Need to decide: 1) include MAS binary / assets in the same package but run a second process, or 2) run MAS as a child service through Cloudron's `run.yml`/`start.sh`. Need to inspect existing packaging to see how (1) Synapse currently runs (maybe `start.sh`), (2) if additional processes are possible (should be via background start commands). Cloudron package manifest may need adjustments to expose MAS endpoints via additional subdomain or path.
  - The existing `start.sh` is an idempotent bootstrap that provisions `homeserver.yaml` from the pip-installed Synapse, copies a static `homeserver.yaml.template`, writes generated secrets, and configures the database, email, OIDC (if Cloudron-provided), TURN, and logging before finally `exec`-ing Synapse with `gosu`. Adding MAS will require launching a second process (probably before the `exec`) so we can keep `start.sh` running both MAS and Synapse. Cloudron apps expose a single HTTP port (`8008` per `CloudronManifest.json`), so MAS would need to listen on a different port and rely on Cloudron’s reverse proxy rules (manifest may need to expose additional `exposePorts` or route via a subpath). 
- **OpenID integration**: MAS expects to be an OIDC provider. Cloudron uses OpenID Connect to allow users to log into the dashboard/app. The original Cloudron issue (https://forum.cloudron.io/topic/13648) mentioned `openid uri configuration issue for synapse-s-mas`. We need to ensure MAS's `.well-known/openid-configuration` URL is accessible and correctly registered in Cloudron. This might require adding proper `manifest.json` entries so MAS endpoints are published to Cloudron's OIDC routing layer.
- **Element/Element X login improvements**: MAS unlocks QR-code login, passkeys, etc. Need to ensure the packaged MAS supports the flow required by Element/Element X (i.e., MAS must report as the OIDC server for `matrix.org` domain). The `homeserver.yaml.template` might need updates to point at MAS discovery endpoints.
- **Cloudron assets**: Determine how to ship MAS assets (frontend/policy/manifest) with the package so MAS can locate them without needing network downloads (Cloudron apps need offline reliability). Could use `test/` folder to store sample config? Need to ensure `start.sh` extracts these assets and sets environment variables.

## Observations from the current package
- `CloudronManifest.json` exposes only `httpPort` 8008, so Synapse listens there. There are addons for localstorage, oidc, postgresql, sendmail, and optional TURN, meaning Cloudron will inject database, mail, and OIDC env vars. Introducing MAS likely requires either:
  - adding `exposePorts` or `httpService` entries so the reverse proxy knows about MAS’s port, and optionally an `oidc` addon entry for MAS’s `.well-known` metadata, or
  - routing MAS through the same HTTP port but behind a different path (e.g., `/auth`). The docs for MAS mention it should run on a dedicated domain, but we might be able to serve it on a subpath if Cloudron doesn’t allow multiple ports.
- `start.sh` already uses environment-supplied OIDC configuration when Cloudron provides it. That logic may need to be extended so MAS can either (a) act as the provider and register itself with Cloudron, or (b) rely on Cloudron’s OpenID stack if MAS is configured as a relying party. The script currently does not interact with Cloudron beyond templating `homeserver.yaml`, so we have full control over how MAS is provisioned once we decide where to run it.

## Recent implementation notes
- `CloudronManifest.json` now advertises a second `httpService` named `mas` on port `4000` so a Cloudron TLS route can reach the MAS discovery endpoints at `/mas/.well-known`.
- Added `mas/mas-config.template.yaml` plus `mas/README.md` so the package now ships an editable MAS config skeleton, expected assets directory, and guidance on where upstream binaries live.
- `start.sh` generates `/app/data/configs/mas.yaml`, keeps a persistent MAS client secret, and is ready to launch `mas-cli server --config ...` with proper signal handling.
- `mas/` now holds the upstream v1.7.0 release artifacts: the `mas-cli` binary plus `share/` assets (frontend, manifest, policy, translations) that the config template points to, enabling MAS to run without building from source.

## Manifest & runtime guardrails
- Cloudron manifest v2 gives every app a single declared `httpPort`, but you can add `httpServices` entries if you need additional HTTPS-terminating services routed through Cloudron’s reverse proxy. Each `httpService` can specify a `port`, `path`, `certificate`, and `protocol`, making it possible to expose MAS on a different internal port or mount it under a distinct path (e.g., `/auth`). Alternatively, `exposePorts` allows you to expose TCP ports directly if a separate plain TCP route is acceptable.
- The existing `oidc` addon signals Cloudron to proxy `.well-known/openid-configuration`. To surface MAS’s discovery documents we can either:
      - register MAS as a second HTTP service with its own path for `.well-known/`, or
      - keep MAS on the same port and let the reverse proxy forward `/auth/.well-known/*` to the MAS port.
    - Since MAS needs to run alongside the homeserver, `start.sh` now writes `/app/data/configs/mas.yaml`, backgrounds `mas-cli server --config ...`, and installs traps so signals kill both services before the script exits, keeping the container responsive while the MAS service shares the same app lifecycle.
    - The script also configures Synapse’s `homeserver.yaml` to treat MAS as its login provider: password registration is disabled and the MAS OIDC endpoints/secret are templated at startup so Element clients see an OIDC-capable homeserver.

## Rough plan for MAS implementation
1. **Gather upstream assets**
   - Confirm we can download a MAS release tarball as part of the build (prefer Docker image if Cloudron supports it, otherwise pre-built binary).
   - Verify what assets need to be packaged (frontend dist, policy wasm, translations, templates, `mas-cli`). Document in this repo how they will be bundled.
2. **Process orchestration**
   - Update `start.sh` to launch MAS alongside Synapse (probably via `&` background process) and ensure proper log capture.
    - Ensure MAS listens on a different port (e.g., `4000`), while Synapse remains on its port. Cloudron reverse proxy must route `/mas` or assign a subdomain (maybe `auth.<app domain>`). Need to explore Cloudron manifest to see if multiple ports can be exposed; if not, we may need to run MAS on the same port but separate path? Need to review Cloudron packaging docs.
    - Sketch a background-run pattern: configure MAS before Synapse, run `/app/pkg/mas/mas-cli server --config ...` as `gosu cloudron:cloudron ... &`, save the child PID, and trap SIGTERM/SIGINT so both MAS and Synapse are terminated when the container stops; the script can then `wait` on Synapse while MAS serves requests in the background.
3. **Configuration mapping**
   - Determine MAS config file structure and defaults. We'll likely need `mas-config.yaml` referencing Synapse endpoints, database credentials, and OIDC discovery data. Need to map Cloudron config variables (domain, TLS cert path) into MAS's config.
   - Update `homeserver.yaml.template` to include the `oidc` settings pointing at MAS (including `client_id`, `client_secret`, `authorization_endpoint`, etc.). This may require new templating variables that Cloudron populates at runtime.
4. **Cloudron integration (OpenID provider)**
   - Evaluate how Cloudron registers OpenID providers for apps; we might need to adjust `CloudronManifest.json` or `start.sh` to register MAS's `.well-known/openid-configuration` with Cloudron (maybe through environment variables or `start.sh` hooking into Cloudron's OpenID provider interface). Need to research Cloudron packaging guidelines for apps that expose their own OIDC endpoints.
   - Identify required scopes and metadata so MAS appears as the identity provider for Element clients used by Cloudron.
5. **Test flows (Element, CLI)**
   - Ensure Element clients can authenticate via MAS (login flow). Document manual steps to test after packaging.
   - Provide instructions for administrators to configure MAS if Cloudron-specific modifications (domain names, secrets) are needed.
6. **Documentation/Assets**
   - Update README or create a new `docs/` entry explaining how MAS is configured for Cloudron (OAUTH endpoints, necessary environment variables).
   - Add `POSTINSTALL.md` or similar update to inform Cloudron admins of new MAS dependencies.

## Next steps (action items)
1. **Clarify process/port constraints**: confirm whether Cloudron allows exposing two ports or mapping a subpath to MAS; if the manifest must change, note which keys support the MAS discovery endpoints. Ensure `start.sh` can launch MAS before Synapse `exec`.
2. **Fetch latest MAS release** (prefer Docker image if Cloudron supports pulling `ghcr.io/element-hq/matrix-authentication-service:latest`). Determine how to extract assets and integrate into our package (hopefully by storing release tarball in repo or downloading during install?).
3. **Define MAS config template** that references Cloudron environment variables (domain, TLS certs, database credentials). Draft a template config file in `test/` or new folder.
4. **Map OpenID requirements**: find Cloudron docs for apps that need to expose OIDC metadata. Write down the necessary manifest keys or scripts to register MAS endpoints.
5. **Document user flows**: in this repo, outline how MAS interacts with Synapse and Element (i.e., MAS obtains upstream login info, issues tokens to Synapse, Element authenticates via Synapse -> MAS). This can serve as both reference and testing checklist.
6. **Additional research**: determine if Cloudron's OpenID stack can act as an upstream provider for MAS (i.e., MAS is the relying party to Cloudron's OIDC provider) or if MAS should be the provider and Cloudron just routes to it.

Once the above are addressed, we'll have a clearer technical path for implementing MAS within this package. Let me know if you'd like me to iterate on any of these sections or move into prototyping a MAS-powered build.
