Repository navigation
Accounts: web link flow and user area (#/me) - #106
Merged
Merged
Conversation
/link redeems the bot's single-use code after a CyberdyneAuth sign-in in the browser that opened it (prompt=login): the link is made only when userinfo reports the email verified, its HMAC equals the consented one, and userinfo.sub matches both token subjects, in one transaction with the code's redemption. The bot then DMs the masked email with a persistent [Unlink]. The user area lives on the admin API origin behind its own __Host-cf_user cookie and middleware: /me/session, /me/privacy, /me/feature-requests and /me/erase, each resolving the person only from the session's linked subject. Console and user sessions are 401 on each other's routes. Erase needs a fresh sign-in (max_age=300, auth_time from the verified id token within 5 minutes), the typed word and the CSRF header, then ends the link and every session of the account and revokes the refresh token. Migration 0036 adds user_session, person_account_link.email_hint/notified_at, the 'web' feature-request source, and deletes the linked account's user sessions in purge_person_derived. The Svelte bundle gains a separate #/me area (userApi.ts, viewmodels/me, views/me) with an architecture rule against imports between it and the console.
The consented email is whatever the Discord person typed, so someone could run /account with a victim's email and send them the /link URL; the victim's verified sign-in then linked their CyberdyneAuth account to the attacker's Discord person, and the Unlink DM went to the attacker. GET /link now starts nothing: it shows a page naming the Discord account the code belongs to, and only its form (POST /link, Origin required and same origin) starts the sign-in. /me/session names the linked Discord account, and POST /me/unlink (with an Unlink button in the user area) undoes a link from the CyberdyneAuth side. The refusal for an account linked elsewhere points there. Also cover checks no test pinned: the sub of a refreshed id or access token, a stored access token for another sub, an auth_time in the future, SameSite=Strict on the user cookie, the user-purpose guard in complete(), and a relink being announced again (notified_at reset, MARK_ANNOUNCED guard).
# Conflicts: # console/src/styles.css # docker-compose.yml # docs/admin-console.md # src/chatmemory/entrypoints/admin.py # src/chatmemory/entrypoints/bot.py # tests/unit/test_compose_env.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the web side of account linking and a user area in the admin process:
/link?code=names the Discord account the code was issued for; its same-origin form starts a CyberdyneAuth sign-in, and the callback links only a verified email whose HMAC matches the consented one, for an unused, unexpired code.#/me: the person's /privacy dashboard, "delete everything" (needs a sign-in within 5 minutes), their suggestions (sourceweb), unlink and logout. Sessions behind__Host-cf_user, separate from the console's.Migration 0036 (revises 0035): user_session, person_account_link.email_hint/notified_at, feature_request source
web; purge_person_derived restated with the user sessions deleted through the link.On when ADMIN_OIDC_* sign-in is configured and ACCOUNT_PROVISIONING_ENABLED=true with PROVISIONING_EMAIL_KEY on the admin service. Merged with main's usage screen and feature-request triage (both bot sweeps and both doc sections kept).
Tests: unit + integration + e2e green locally; alembic upgrade / downgrade -1 / upgrade clean; console lint/test/build green; mypy, ruff, openspec strict clean.