1
0
Fork 0
mirror of https://github.com/coko7/watari.git synced 2026-09-17 09:05:38 +00:00
Web GUI frontend for rustypaste with OpenID Connect SSO and optional client-side encryption.
  • Rust 73.6%
  • HTML 10.2%
  • JavaScript 9.6%
  • CSS 6%
  • Dockerfile 0.6%
Find a file
Coko 2e04ae7104
ci(docker): add publish workflow, refactor to traefik (#5)
* ci(docker): add publish workflow, refactor to traefik

Add Docker image publishing on release. Remove embedded rustypaste
(external now). Switch to traefik routing (clean deployment, TLS
termination). Externalize configuration via environment variables.
Document OIDC groups for Zitadel, Microsoft Entra ID.

* docs(README): add vibe-coding mention + ToC
2026-08-18 07:54:13 +02:00
.github/workflows ci(docker): add publish workflow, refactor to traefik (#5) 2026-08-18 07:54:13 +02:00
assets feat(ui): redesign layout with sidebar navigation and dark mode 2026-07-06 20:22:38 +02:00
migrations refactor: rename project from KyoSabi to Watari 2026-07-05 11:30:46 +02:00
src chore: run cargo fmt --all 2026-08-18 07:16:17 +02:00
static feat(ui): redesign layout with sidebar navigation and dark mode 2026-07-06 20:22:38 +02:00
templates feat(ui): redesign layout with sidebar navigation and dark mode 2026-07-06 20:22:38 +02:00
.dockerignore feat: implement KyoSabi per kyosabi.md spec 2026-07-03 11:25:03 +02:00
.gitignore feat: implement KyoSabi per kyosabi.md spec 2026-07-03 11:25:03 +02:00
.release-please-manifest.json chore(main): release watari 1.0.0 2026-08-18 07:24:12 +02:00
Cargo.lock chore(main): release watari 1.0.0 2026-08-18 07:24:12 +02:00
Cargo.toml chore(main): release watari 1.0.0 2026-08-18 07:24:12 +02:00
CHANGELOG.md chore(main): release watari 1.0.0 2026-08-18 07:24:12 +02:00
CLAUDE.md refactor: rename project from KyoSabi to Watari 2026-07-05 11:30:46 +02:00
docker-compose.yml ci(docker): add publish workflow, refactor to traefik (#5) 2026-08-18 07:54:13 +02:00
Dockerfile refactor: rename project from KyoSabi to Watari 2026-07-05 11:30:46 +02:00
env.example ci(docker): add publish workflow, refactor to traefik (#5) 2026-08-18 07:54:13 +02:00
LICENSE Initial commit 2026-06-30 23:13:07 +02:00
README.md ci(docker): add publish workflow, refactor to traefik (#5) 2026-08-18 07:54:13 +02:00
release-please-config.json ci(release): add release-plz automation 2026-07-06 18:13:48 +02:00
rustypaste-config.example.toml refactor: rename project from KyoSabi to Watari 2026-07-05 11:30:46 +02:00
token-bindings.example.yaml refactor: rename project from KyoSabi to Watari 2026-07-05 11:30:46 +02:00
watari.md refactor: rename project from KyoSabi to Watari 2026-07-05 11:30:46 +02:00

Watari

Note

🤖 This project has been vibe-coded with Claude. Read bottom section to learn more.

Watari is a web GUI frontend for rustypaste.

The project name comes from the japanese word 渡り (watari, also written as ワタリ in Katakana) which means "crossing, passage, transit" and symbolizes the relationship with rustypaste.

Watari banner image

Release info License: MIT Rust Tests

Warning

🚧 Early stages — big work in progress. Expect rough edges and breaking changes. 🚧

On top of providing a GUI, it comes with some additional features:

All built with a based technical stack: axum + Askama + HTMX + SQLite

Watari UI screenshot

Table of contents

  1. cp env.example .env and fill in SESSION_SECRET (openssl rand -hex 32), OIDC_CLIENT_SECRET, and two distinct RUSTYPASTE_TOKEN_* secrets.
  2. cp rustypaste-config.example.toml rustypaste-config.toml and paste the same two rustypaste token values into auth_tokens/delete_tokens.
  3. cp token-bindings.example.yaml token-bindings.yaml and adjust the groups to match your IdP (see "OIDC groups setup" below).
  4. Edit docker-compose.yml's OIDC_ISSUER_URL, OIDC_CLIENT_ID, APP_BASE_URL/RUSTYPASTE_PUBLIC_URL for your deployment.
  5. docker compose up -d --build

OIDC groups setup

Watari maps OIDC groups to rustypaste tokens via token-bindings.yaml (§7 in watari.md), so the groups claim must actually be present in the ID token. Two env vars control this: OIDC_GROUPS_CLAIM (which claim to read groups from) and OIDC_GROUPS_SCOPE (an extra scope some IdPs need requested before they'll populate that claim).

Zitadel — groups come from project roles, not org groups:

  1. In your Zitadel project, define roles under Roles, then grant them to users (directly or via an org role grant).

  2. Either enable "Assert Roles on Authentication" in the project's general settings, or request the roles scope explicitly — Watari does the latter:

    OIDC_GROUPS_CLAIM=urn:zitadel:iam:org:project:roles
    OIDC_GROUPS_SCOPE=urn:zitadel:iam:org:project:roles
    
  3. token-bindings.yaml's groups entries should match the role keys you defined (e.g. admin, user).

Microsoft Entra ID — groups come from the token configuration, no extra scope needed:

  1. In the app registration, go to Token configurationAdd groups claim, and pick Security groups (or All groups). Add it to the ID token.

  2. Leave OIDC_GROUPS_SCOPE unset; set:

    OIDC_GROUPS_CLAIM=groups
    
  3. By default Entra ID emits group object IDs (GUIDs), not names — token-bindings.yaml's groups entries need to be those GUIDs. Alternatively, use App roles instead of security groups (assign users/groups to roles in the app registration) and set OIDC_GROUPS_CLAIM=roles, which emits the human-readable role value strings instead.

  4. Entra ID caps the groups claim at 200 groups per token ("overage") — above that it omits groups entirely and expects a Graph API call instead, which Watari does not do. Prefer App roles if a user could belong to that many groups.

Running locally for development

Requires Rust (edition 2024, so a recent stable toolchain) and no external services besides an OIDC provider and a rustypaste instance to point at.

cargo build
cargo test
export $(cat .env | xargs)  # or set the vars below directly
cargo run

Required environment variables (see watari.md §5 for the full list with defaults): OIDC_ISSUER_URL, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_REDIRECT_URI, SESSION_SECRET, RUSTYPASTE_INTERNAL_URL, RUSTYPASTE_PUBLIC_URL, APP_BASE_URL. A token-bindings.yaml must also exist at TOKEN_BINDINGS_PATH (default token-bindings.yaml), with each env_var it references set.

Database migrations run automatically at startup (DATABASE_PATH, default /data/app.db — for local dev, point this somewhere writable, e.g. ./dev.db).

Project layout

  • src/ — the Axum application; see CLAUDE.md for a module-by-module map.
  • templates/ — Askama HTML templates, compiled into the binary at build time.
  • static/ — served as-is at /static (vendored HTMX, app.css, app.js).
  • migrations/ — sqlx SQL migrations, embedded into the binary at build time.
  • token-bindings.example.yaml — OIDC-group → rustypaste-token mapping (§7).
  • rustypaste-config.example.toml — matching rustypaste server config.

License

AGPLv3 — see LICENSE.

AI usage / vibe coding

The initial project scaffolding was done via a technical spec generated by Claude and further features/fixes have been done with Claude as well.

I have spent some time reading through the code, testing and troubleshooting things myself but far less than I should have given the current project size.

I would like to reduce my AI usage and take back ownership of the code but I have honestly haven't had the time to do so.