docs(android): add trusted-devices/MFA live smoke-test screenshots
Live end-to-end smoke test of the Android trusted-device + recovery-code
feature (app PR RunicGateway/Android-app#23) against the local server +
MariaDB on an API 36 emulator. Adds android/screenshots/ with five
captures (login trust step, account Security section, Trusted Devices,
recovery-codes show-once, recovery-code login) and a README documenting
the verified flows — including that trust survives logout (password-only
re-login skipped TOTP) and untrust-all clears the local token.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
@
docs(android): record trusted-devices app implementation in PLAN §4.1.1
Marks §4.1.1 implemented (app PR RunicGateway/Android-app
feature/trusted-devices-mfa) and captures two deliberate design
decisions from the build:
- The trust token DELIBERATELY SURVIVES logout (native analogue of the
rg_trust cookie): it is only consulted at a fresh login, so clearing
it on logout would make the feature a no-op. Kept in a separate,
username-scoped encrypted store; cleared only on Settings→Server
switch, untrust-all, or server-side revocation. Supersedes the earlier
handoff note.
- The login-time trust cap is surfaced + resolved on the Trusted Devices
screen rather than a blocking login modal, since native login already
issued the session.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
@
Add TRUSTED_DEVICES_MFA.md (the approved design/implementation plan) and fold
the feature into BACKEND_DESIGN §3 (trusted_devices + recovery_codes schema),
§4 (login/totp trust+recovery, /auth/me/trusted-devices*, recovery-codes*,
admin trusted-device + /mfa/reset routes), and §6 (trusted-device security
model + audit actions). Note the app-side trust/recovery flow in android PLAN §4.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add docs/website/ARCHITECTURE.md (canonical copy of the website architecture
Mermaid diagram, with fuller notes) and embed the same diagram in the
website-README mirror. Mirrors the diagram added to the website repo README.
Co-Authored-By: Claude <noreply@anthropic.com>
Record the M10 plan and correct the admin-scope contract:
- §1: narrow the app's exclusion list. The operational admin subset is now
IN scope for staff (moderation, support queue, dashboard/site-mode, content =
news posts + wiki cats/tags). Only the hero/CMS block editor, Discord-bot
config, uo-link config, and OAuth-provider setup remain excluded.
- §6.4: self-service stays role-agnostic under /auth/me/*, but the operational
admin subset now calls /api/v1/admin/** directly, gated by a STAFF/ADMIN menu
access level; bearer is accepted and role re-checked every request.
- §9: add milestone M10 covering the SSO discovery/reachability fixes (native
buttons, no website fallback, encrypted pending PKCE, scrollable drawer, dev
stub IdP) and the staff-operations screens.
Co-Authored-By: Claude <noreply@anthropic.com>
Document the test plan for the bot/ workspace — the last of the three website
npm workspaces without a suite (server + client landed in website PR #86).
Records the shared node --test conventions (no jest/vitest/jsdom; DB pool at a
dead port; Discord objects hand-faked) and maps the meaningful bot behavior to
lock: the normalize/duration/spam pure logic, the invite/site-api/internal-key
single-collaborator units, the messageFilter pipeline (bypass-first decision
order + fixed-duration mute + best-effort recording), and the models with real
shaping logic. Includes the CI + SonarQube coverage wiring to mirror PR #86 and
a suggested phasing.
Co-Authored-By: Claude <noreply@anthropic.com>
Record that the app's HTTPS-only-in-release / HTTP-in-debug rule (ServerUrl,
allowInsecureHttp = BuildConfig.DEBUG) is backed at the platform socket layer
by an explicit network security config: main/release forbids all cleartext, a
debug override re-permits cleartext to loopback only. Matches the fix in
RunicGateway/Android-app (fix/manifest-cleartext-traffic).
Co-Authored-By: Claude <noreply@anthropic.com>
Adds docs/ci/SONARQUBE.md covering the non-blocking push-to-main scan
wired into website, link, and Android-app: server URL, per-repo project
keys/sources, the SONAR_TOKEN secret + SONAR_HOST_URL variable, and how
to onboard a new repo.
Co-Authored-By: Claude <noreply@anthropic.com>
Replace the vague "helmet with a CSP suited to the SPA" line with the actual
policy now implemented in server/src/app.js: per-directive sources and the
rationale for each non-'self' allowance (Google Fonts, inline React styles,
external/embedded images, same-origin REST+SSE), why upgrade-insecure-requests
is omitted, the scoped looser CSP for the /api/docs Swagger UI route, and the
X-Powered-By handling across the public and internal listeners.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
Promote APP_LINKS.md from a deferred design note into an implementation spec
matching the website `feat/mobile-app-links` and android `feat/app-links`
branches: the server-side `/.well-known/assetlinks.json` route + `mobile_app_links_enabled`
toggle + additive redirect-allowlist entry, and the app-side `autoVerify`
intent-filter driven by a build-time `appLinkHost` (a single multi-tenant APK
cannot autoVerify open-ended shard domains, so App Links are a white-label /
first-party build opt-in; the custom scheme stays the permanent fallback).
Update PLAN.md §9 (M9 follow-up) and the §14 open item, and the redirect-URI
allowlist section of website/BACKEND_DESIGN.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
Add the "M9 plan — native SSO login" block to android/PLAN.md: the two-part
(backend-first) split, the frozen Part-1 bridge contract the app codes against
(/auth/providers, /auth/mobile/sso/start Custom-Tab redirect, the code/error
callback deep link, /auth/mobile/sso/exchange), and the six Part-2 app work
items (PKCE+state, SsoAuthManager, SsoApi+DTOs, the callback intent-filter,
the login-screen provider list, and the JVM tests).
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
Record the plan before coding: native Android "Sign in with Google/Discord"
via a Mobile SSO Authorization Bridge that extends the existing /auth/sso/*
redirect flow and terminates in the existing mobile bearer tokens.
- BACKEND_DESIGN.md: mobile_auth_sessions / mobile_auth_codes schema, the
/auth/mobile/sso/{start,exchange} contract, the two PKCE layers, state/CSRF,
exact-match redirect-URI allowlist, TOTP parity, and the documented
revocation-latency window.
- android/PLAN.md: promote §4.2's "possible later enhancement" to milestone M9
(backend-first, mirroring M7); status note.
- android/APP_LINKS.md: new architecture note on the per-shard assetlinks.json
/ pairing multi-tenancy question (App Links deferred; custom scheme only now).
Co-Authored-By: Claude <noreply@anthropic.com>
Flip M7 Part 2 to landed (Android-app#15) and record the two implementation
decisions: the direct-ntfy embedded distributor (no UnifiedPush library — the
plan's stated likely path; foreground-service SSE, no second app, no Google
Play Services), and the small additive push.ntfyUrl settings field the app
needs to discover the relay (website#79). Document push.ntfyUrl +
NTFY_PUBLIC_URL in BACKEND_DESIGN.md.
Co-Authored-By: Claude <noreply@anthropic.com>
Part 1 backend landed (website#78 merged); flip its status to landed and
expand the M7 plan block into a detailed Part 2 (app) plan, grounded in the
merged /auth/me/devices + notifications contract.
Transport decision (per user): the app EMBEDS its own UnifiedPush
distributor — ntfy is only the relay server, no second app installed, no
Google Play Services. A foreground-service persistent ntfy connection
(reusing the ShardStreamClient pattern) subscribes to the app's own topic;
the registered endpoint is that topic URL. A PushTransport seam keeps the
future FCM Play flavor cheap.
Also records the ten Part-2 work items, resolves the §13 notification-tap
deep-link open item, and drops the now-decided distributor-strategy question.
Co-Authored-By: Claude <noreply@anthropic.com>
- BACKEND_DESIGN.md: push_devices + notification_subscriptions tables (§3), the
/auth/me/devices* + /auth/me/notifications/* API rows (§4), a push-notification
design + security section (content-free tickles, PUBLIC_KINDS split, owner-keyed
personal streams, SSRF endpoint guard, untrusted-relay model), and the ntfy
compose service in the deploy section (§8).
- PLAN.md: flip M7 Part 1 (backend + docs) to in-review — status line, §8 item 3,
§9 M7.
Co-Authored-By: Claude <noreply@anthropic.com>
Capture the M7 backend/docs breakdown in PLAN.md before the code lands: two
event sources / one publisher, the stream catalog + PUBLIC_KINDS-gated mapping,
push_devices + notification_subscriptions tables, the /auth/me routes, the SSRF
endpoint guard, and the content-free-tickle ntfy service (no publish token).
Co-Authored-By: Claude <noreply@anthropic.com>
Mark M6 landed (RunicGateway/Android-app#11): signed-APK release plumbing
(R8 minify + resource shrink, release signingConfig from a gitignored keystore,
release.yml on a v* tag), the §3 version-mismatch guard, and the default brand
app icons (deep-indigo medallion). Record the decision to descope the optional
biometric app-lock from v1 (tokens already encrypted at rest) across §4.3, the
M3 note, §9, and §13.
Co-Authored-By: Claude <noreply@anthropic.com>
Mark the M5 shard-website design pass complete in docs/android/PLAN.md,
matching RunicGateway/Android-app#10: dark-only theme (deep blue-black
surfaces, slate accent, Cinzel display face), reusable pill/label/card/meter
components, and retained per-shard brand-accent seeding — restyling the
working M1–M4 screens with no architecture, data-flow, endpoint, or DTO
change. Updates the status header, the §9 build-progress record, and the
milestone list (M0–M5 landed; M6 release hardening next).
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
Marks M4 done in android/PLAN.md §9 build-progress and flips the top
status to "M0–M4 landed; M5 (design pass) next." Documents the account
self-service (/auth/me/account*), game-account linking, and text-only
own game-data screens shipped in RunicGateway/Android-app#9 — a pure
consumer of the existing bearer API, no backend/protocol change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
Records the M3 functional auth pass in docs/android/PLAN.md: native
username/password (+TOTP) login, EncryptedSharedPreferences token storage,
the refresh-on-401 authenticator, /auth/me resume re-validation, the
declarative access-level menu + My Account, and the Custom-Tab hand-offs for
register / forgot-password / SSO. Also records the decision to defer the
optional biometric app-lock to M6 (tokens are already encrypted at rest).
No backend/API change accompanied M3 — the app is a pure consumer of the
existing mobile bearer + /auth/me surface — so no Swagger regeneration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
Mark M2 done in the build-progress section: the public shard widgets over
/public/shard/* (hub + champ/guild/governor/house boards) and the live SSE
feed with self-driven reconnect/backoff (Android-app#7). Update the status
line to "M0–M2 landed; M3 next". No API change — the app consumes the
existing public shard surface.
Co-Authored-By: Claude <noreply@anthropic.com>
Mark M0+M1 done in the build-progress header and next up M2. Summarize
the M1 functional pass (first-run connect, runtime base URL + host
interceptor, layered ApiResult stack, brand-seeded theming, public
content/wiki/pages/contact screens) and record the deliberate
hand-written-vs-openapi-generated API-client deviation from §2 and its
rationale (swagger-autogen schemas are meta-descriptive, not
codegen-clean). Tracks RunicGateway/Android-app#6.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr
Update the PLAN.md status header now that the Android-app repo scaffold
(RunicGateway/Android-app#2) is in: Gradle+Compose+Hilt skeleton, version
catalog, and CI. Records M0 done and points at M1 (functional Kotlin pass).
Co-Authored-By: Claude <noreply@anthropic.com>
Counterpart to RunicGateway/website#77.
- BACKEND_DESIGN.md: /public table now documents the new GET /public/version
(DB-free identity/version), the version block on /public/status, and the brand
block on /public/settings (per-shard theming: name/accent/logo/hero/favicon).
- android/PLAN.md: mark §8 item 4 (version/health) and item 6 (branding) DONE and
update the prerequisite-progress summary — all v1 prerequisites are now done;
only push notifications (item 3) remains and is post-v1 (M7). App M0–M4 unblocked.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgyHnrNa8WwG3doxvxjuCr