Per the owner's spec: each social connection gets publishGovernance in its fields — unset = manual publish (today), auto = dispatch on approval, admin1/admin_majority/admin_consensus = a publish-phase chatgov poll (subject draft_publish, its own open-poll slot, no collision with review gates). Dispatch holds until the publish poll passes (E3 pre-dispatch check); auto dispatches on approval. Includes migration 033, the PATCH /connections/:id/publish-governance route (chatgov.manage), and 19+31 new tests. Implementation by the branding-panel process (claude/opus), lint and integration fixes here.
215 lines
13 KiB
Markdown
215 lines
13 KiB
Markdown
# Chat sign-in restyle and deployment report
|
|
|
|
Repo implementation only; no production connection, deployment, or git commit
|
|
was made. The server-owned `/opt/occ-element/config.json` is not in this repo.
|
|
The supplied patch merges into that file rather than replacing its configuration.
|
|
|
|
Signed-out visitors opening `chat.occupymedia.cc` will see a small Hub mark and
|
|
wordmark in the top-left, a centered card containing **Sign in**, username and
|
|
password fields, and a red submit button. Password recovery and account creation
|
|
remain available as quiet links. Registration uses the same compact card. The
|
|
background is `#060403`, the card is `#0F0A09`, and the font is system-ui. The
|
|
mark is capped at 32px; there is no logo sidebar, background artwork, or hero.
|
|
Long forms and errors scroll on small screens rather than overlapping the brand.
|
|
Element's footer remains small and muted.
|
|
|
|
## Verified Element Web 1.12.30 behavior
|
|
|
|
No Element source or config template was found in the repository or its installed
|
|
dependencies. Research used the official **v1.12.30** source archive and the
|
|
matching `ghcr.io/element-hq/element-web:v1.12.30` image, in temporary local files.
|
|
|
|
| Configuration | Effect in 1.12.30 |
|
|
| --- | --- |
|
|
| `branding.auth_header_logo_url` | Image source in login/registration headers and the default welcome component. This is nested under `branding`, not a top-level key. |
|
|
| `branding.logo_link_url` | Link destination where Element actually renders a linked logo, such as default welcome. |
|
|
| `auth_header_logo_click_url` | Does not exist in this release. The login/registration header renders an unlinked image; a config option cannot make that header clickable. |
|
|
| `brand` | App name used in translated text; does not change the header's layout or image. |
|
|
| `branding.welcome_background_url` | Background artwork across auth pages. The injected CSS replaces the inline background with a solid color. |
|
|
| `embedded_pages.login_for_welcome` | Uses the login form for the signed-out landing page, bypassing default/custom welcome content. |
|
|
| `default_server_config` | Selects the homeserver and identity-server connection details; does not control branding or layout. Left intact. |
|
|
| `disable_custom_urls` | Removes server editing. The CSS hides the redundant server label only when the edit control is absent. |
|
|
| `disable_3pid_login` | Removes the username/email/phone selector, leaving username/password. |
|
|
| `disable_login_language_selector` | Removes the language dropdown from the auth header. |
|
|
|
|
See the pinned [configuration docs](https://github.com/element-hq/element-web/blob/v1.12.30/docs/config.md),
|
|
[AuthHeaderLogo source](https://github.com/element-hq/element-web/blob/v1.12.30/apps/web/src/components/views/auth/AuthHeaderLogo.tsx),
|
|
and [DefaultWelcome source](https://github.com/element-hq/element-web/blob/v1.12.30/apps/web/src/components/views/auth/DefaultWelcome.tsx).
|
|
|
|
The structure is `.mx_AuthPage` → `.mx_AuthPage_modal` →
|
|
`main.mx_AuthPage_modalContent`, with `.mx_AuthHeader` and `.mx_AuthBody` as
|
|
siblings. The large logo comes from `.mx_AuthHeaderLogo > img` inside a 206px
|
|
sidebar; the original body is 500px wide. The wrapper also renders a blur layer
|
|
and `.mx_AuthFooter`. See [AuthPage](https://github.com/element-hq/element-web/blob/v1.12.30/apps/web/src/components/views/auth/AuthPage.tsx)
|
|
and [upstream auth CSS](https://github.com/element-hq/element-web/tree/v1.12.30/apps/web/res/css/views/auth).
|
|
There is no `.mx_AuthPage_logo` in this release's auth structure.
|
|
|
|
`setting_defaults.custom_themes` accepts theme colors, fonts and Compound token
|
|
overrides, not an arbitrary CSS stylesheet URL. `source_url` records a theme
|
|
JSON's origin, not a CSS file. The injected link intentionally has no
|
|
`data-mx-theme`, so Element's theme switching will not disable it. See the
|
|
[theming docs](https://github.com/element-hq/element-web/blob/v1.12.30/docs/theming.md)
|
|
and [theme loader/types](https://github.com/element-hq/element-web/blob/v1.12.30/apps/web/src/theme.ts).
|
|
|
|
On first visits from iOS/Android, Element redirects a bare `/` to
|
|
`/mobile_guide/` **before** loading config. Both chat vhosts redirect that
|
|
app-download page to `/#/login`, which bypasses the mobile redirect. Disabling
|
|
`mobile_guide_toast` also removes the later mobile-app prompt. See the pinned
|
|
[startup source](https://github.com/element-hq/element-web/blob/v1.12.30/apps/web/src/vector/index.ts).
|
|
|
|
## Files changed
|
|
|
|
| File | Purpose |
|
|
| --- | --- |
|
|
| [../edge/hub-chat-auth.css](../edge/hub-chat-auth.css) | Scoped auth overrides: corner branding, compact responsive card, warm colors, focus styles and red primary actions. Uses stable `mx_*` classes, structural selectors and Compound `data-kind`, with no hashed class selectors. |
|
|
| [../edge/nginx.conf](../edge/nginx.conf) | Both HTTP tunnel and HTTPS chat vhosts serve `/hub-chat-auth.css` and inject its link once before `</head>` in HTML. Clears upstream Accept-Encoding so sub_filter can read HTML. Routes the mobile guide to login. Matrix API and SSO helper keep their own locations. |
|
|
| [../edge/docker-compose.edge.yml](../edge/docker-compose.edge.yml) | Read-only bind mount for the stylesheet. |
|
|
| [auth-branding.patch.json](auth-branding.patch.json) | Hub logo URL, supported logo-link setting, direct login landing and removal of extra login selectors. |
|
|
| [apply-auth-branding.py](apply-auth-branding.py) | Merge/preview utility. Preserves unrelated settings and writes in place to retain Docker's single-file bind mount. |
|
|
| [../edge/README.md](../edge/README.md) | Links this report and corrects the documented chat routing. |
|
|
| [AUTH-RESTYLE.md](AUTH-RESTYLE.md) | This research and deployment report. |
|
|
|
|
The stylesheet is downloaded with the SPA shell; nginx cannot see hash routes.
|
|
It applies only within `.mx_AuthPage`, including recovery/auth verification
|
|
screens using that wrapper. Signed-in room UI keeps the existing custom theme.
|
|
The `element.occupymedia.cc` alias vhost is not changed.
|
|
|
|
## Exact deployment steps (operator runs these; not executed here)
|
|
|
|
Use the existing CT 150 checkout at `/opt/anarchoposter`. Run server commands
|
|
with permission to edit `/opt/occ-element/config.json` and manage Docker.
|
|
|
|
1. **On the server, before copying files**, back up the config and edge files.
|
|
Keep this shell open so `occ_auth_backup` remains available for later steps.
|
|
|
|
```bash
|
|
occ_auth_backup="/opt/occ-element/backups/hub-auth-$(date -u +%Y%m%dT%H%M%SZ)"
|
|
mkdir -p "$occ_auth_backup"
|
|
cp -p /opt/occ-element/config.json "$occ_auth_backup/config.json"
|
|
cp -p /opt/anarchoposter/infra/occupymedia/edge/nginx.conf "$occ_auth_backup/nginx.conf"
|
|
cp -p /opt/anarchoposter/infra/occupymedia/edge/docker-compose.edge.yml "$occ_auth_backup/docker-compose.edge.yml"
|
|
if test -f /opt/anarchoposter/infra/occupymedia/edge/hub-chat-auth.css; then
|
|
cp -p /opt/anarchoposter/infra/occupymedia/edge/hub-chat-auth.css "$occ_auth_backup/hub-chat-auth.css"
|
|
fi
|
|
printf 'Backup: %s\n' "$occ_auth_backup"
|
|
```
|
|
|
|
2. **From this workstation's repo root**, copy only the reviewed infra files.
|
|
Set `OCC_EDGE_SSH` to your existing SSH destination for CT 150; no hostname or
|
|
credentials are assumed here.
|
|
|
|
```bash
|
|
OCC_EDGE_SSH='YOUR_EXISTING_CT_150_SSH_DESTINATION'
|
|
rsync -aR -- \
|
|
infra/occupymedia/edge/nginx.conf \
|
|
infra/occupymedia/edge/docker-compose.edge.yml \
|
|
infra/occupymedia/edge/hub-chat-auth.css \
|
|
infra/occupymedia/edge/README.md \
|
|
infra/occupymedia/element/ \
|
|
"$OCC_EDGE_SSH:/opt/anarchoposter/"
|
|
```
|
|
|
|
3. **On the server**, validate the candidate edge config with the new mounts,
|
|
then merge the auth patch and recreate only the edge service:
|
|
|
|
```bash
|
|
cd /opt/anarchoposter/infra/occupymedia/edge
|
|
docker compose -f docker-compose.edge.yml config --quiet
|
|
docker compose -f docker-compose.edge.yml run --rm --no-deps edge nginx -t
|
|
python3 ../element/apply-auth-branding.py /opt/occ-element/config.json > "$occ_auth_backup/config.preview.json"
|
|
diff -u "$occ_auth_backup/config.json" "$occ_auth_backup/config.preview.json"
|
|
python3 ../element/apply-auth-branding.py /opt/occ-element/config.json --write
|
|
docker compose -f docker-compose.edge.yml up -d --no-deps --force-recreate edge
|
|
docker exec occ-edge-1 nginx -t
|
|
```
|
|
|
|
Run each command only if the preceding validation succeeded; `diff` exits 1
|
|
for the expected changes. Recreating the edge is required for the new CSS
|
|
mount and ensures it sees copied files even if their inodes changed. Element
|
|
needs no restart: the merge utility retains the config inode. Its existing
|
|
`setting_defaults.custom_themes`, Compound tokens, `default_theme`, and
|
|
`default_server_config` remain intact. Do not replace config.json with the
|
|
patch JSON or try to register this CSS as a custom theme.
|
|
|
|
4. **On the server**, verify the public HTML, stylesheet and served config:
|
|
|
|
```bash
|
|
curl -fsS --compressed https://chat.occupymedia.cc/ -o "$occ_auth_backup/index.served.html"
|
|
curl -fsS 'https://chat.occupymedia.cc/hub-chat-auth.css?v=1' -o "$occ_auth_backup/auth.served.css"
|
|
curl -fsS https://chat.occupymedia.cc/config.json -o "$occ_auth_backup/config.served.json"
|
|
cmp hub-chat-auth.css "$occ_auth_backup/auth.served.css"
|
|
python3 - "$occ_auth_backup" <<'PY'
|
|
import json, sys
|
|
from pathlib import Path
|
|
backup = Path(sys.argv[1])
|
|
html = (backup / "index.served.html").read_text()
|
|
assert html.count('href="/hub-chat-auth.css?v=1"') == 1
|
|
old = json.loads((backup / "config.json").read_text())
|
|
served = json.loads((backup / "config.served.json").read_text())
|
|
for key in ("setting_defaults", "default_theme", "default_server_config", "default_server_name"):
|
|
assert served.get(key) == old.get(key), key
|
|
assert served["branding"]["auth_header_logo_url"] == "https://app.occupymedia.cc/brand/logo.svg"
|
|
assert served["branding"]["logo_link_url"] == "https://app.occupymedia.cc"
|
|
assert served["embedded_pages"]["login_for_welcome"] is True
|
|
assert served["disable_3pid_login"] is True
|
|
assert served["disable_custom_urls"] is True
|
|
print("Public HTML injection, stylesheet and preserved theme verified")
|
|
PY
|
|
```
|
|
|
|
If a CDN serves an older HTML/config response, purge those URLs and retry.
|
|
In a fresh signed-out browser, open `/`, `/#/login` and `/#/register`, and
|
|
check the page on a phone as well. Check password errors, keyboard focus,
|
|
recovery and an existing signed-in room. Browser reloads load the new config.
|
|
Element also supports domain-specific config files; if this installation
|
|
starts serving a successful `/config.chat.occupymedia.cc.json`, apply the
|
|
same merge to its mounted source because it takes precedence over config.json.
|
|
|
|
Rollback using the printed backup directory: restore the old nginx and compose
|
|
files, restore the old config **in place**, then recreate the edge service with
|
|
the old compose file:
|
|
|
|
```bash
|
|
cp -p "$occ_auth_backup/nginx.conf" /opt/anarchoposter/infra/occupymedia/edge/nginx.conf
|
|
cp -p "$occ_auth_backup/docker-compose.edge.yml" /opt/anarchoposter/infra/occupymedia/edge/docker-compose.edge.yml
|
|
if test -f "$occ_auth_backup/hub-chat-auth.css"; then
|
|
cp -p "$occ_auth_backup/hub-chat-auth.css" /opt/anarchoposter/infra/occupymedia/edge/hub-chat-auth.css
|
|
fi
|
|
python3 - "$occ_auth_backup/config.json" /opt/occ-element/config.json <<'PY'
|
|
from pathlib import Path
|
|
import sys
|
|
data = Path(sys.argv[1]).read_bytes()
|
|
with Path(sys.argv[2]).open("r+b") as target:
|
|
target.write(data)
|
|
target.truncate()
|
|
PY
|
|
cd /opt/anarchoposter/infra/occupymedia/edge
|
|
docker compose -f docker-compose.edge.yml run --rm --no-deps edge nginx -t
|
|
docker compose -f docker-compose.edge.yml up -d --no-deps --force-recreate edge
|
|
```
|
|
|
|
## Local validation
|
|
|
|
- Real Element v1.12.30 and nginx:1.27-alpine ran on an isolated local Docker
|
|
network with temporary certificates and loopback ports; Matrix responses and
|
|
the Hub asset request were mocked. No live accounts or production services
|
|
were accessed.
|
|
- Full repo nginx config passed `nginx -t`; compose configuration parsed.
|
|
Nginx emits an existing duplicate `text/html` MIME warning in the unrelated
|
|
files sign-in location; it does not prevent validation.
|
|
- Both chat HTTP/HTTPS vhosts injected exactly one stylesheet link despite the
|
|
client advertising gzip. JSON and the SSO helper were unchanged; CSS content
|
|
and content type matched the repo file.
|
|
- Chromium checked bare `/` → login, 420px desktop card, 32px corner logo,
|
|
system-ui, warm background, red submit, two login inputs, mock failed login,
|
|
visible errors, and registration. Checked widths 320/390/844px including
|
|
landscape: no horizontal overflow or brand/form overlap. A fresh iPhone user
|
|
agent reached the form through the mobile-guide redirect.
|
|
- The injected link remained enabled after custom-theme loading. A room DOM
|
|
without the auth wrapper retained its original button color.
|
|
- Config merge checks confirmed preservation of theme, Compound tokens,
|
|
homeserver and sibling keys, idempotence, and the original file inode.
|
|
|
|
Real successful authentication and production cache/routing behavior still need
|
|
the operator's post-deployment checks. Existing unrelated workspace changes were
|
|
left alone; no files in `apps/api` were edited by this task.
|