feat: 0.4 stage 4 — account deletion owned by identity + Faza 1 data migration #5

Merged
day01 merged %!d() commits from %!s() into %!s() 2026-08-20 07:29:30 +00:00
Owner

Squashes together: (1) account-deletion confirm/restore/sweep, moved here from Gitea's PR D — mailed confirm/restore links, 30-day window, calls into Gitea's new private API (routers/private/account_deletion.go) to execute the lock/unlock/hard-delete; (2) Faza 1 data-migration seeding (crates/storage/src/seed.rs, insert_repository, src/bin/import_seed) plus claim-account-by-verified-email in find_or_create_user_by_link.

See syncode PR (same branch name) for the matching Go-side changes.

Squashes together: (1) account-deletion confirm/restore/sweep, moved here from Gitea's PR D — mailed confirm/restore links, 30-day window, calls into Gitea's new private API (routers/private/account_deletion.go) to execute the lock/unlock/hard-delete; (2) Faza 1 data-migration seeding (crates/storage/src/seed.rs, insert_repository, src/bin/import_seed) plus claim-account-by-verified-email in find_or_create_user_by_link. See syncode PR (same branch name) for the matching Go-side changes.
day01 added 2 commits 2026-08-20 07:22:56 +00:00
		Mirrors the email_verification pattern: a mailed confirm link starts
the flow, a hashed token proves it, and a second mailed restore link
undoes it within 30 days. The account lock/unlock/hard-delete itself
still happens in Gitea (repo/org/package ownership lives there), so
the confirm handler calls into Gitea's new private API before
committing confirmed_at — a still-owned account gets a specific
reason back instead of a silent lock.

New crate gitea-client wraps that internal API (same shared secret
syncode-control already uses). An hourly sweep in main.rs hard-deletes
accounts whose restore window has closed.
	
		Adds the storage/binary side of the one-time ETL that backfills
syncode-identity from Gitea's existing users/orgs/teams/repos/grants
(0.4 stage 4, Faza 1): idempotent seed_* functions (upsert by natural
key — username, slug, org+name, owner+name — so the import tool is
safe to re-run) plus a new insert_repository, and a bin/import_seed
that reads the Go side's export-seed JSON and writes back a
{gitea_id: uuid} mapping for Go's identity_link backfill. Grant rows
aren't deduplicated on re-run — harmless since capabilities are
unioned, not counted, but means this only runs once per environment
against a reviewed file.

Also changes find_or_create_user_by_link to check verified_emails
against user_email before creating a new user — a match on both this
forge's and the login's independently-verified claim is what makes
Faza 1's pre-seeded accounts (verified email, no linked_identity yet)
claimable on first login instead of ending up duplicated, and covers
the same case organically for anyone linking a second provider that
shares a verified address with their first.
	
day01 merged commit 284e7ad2dd into %!s() 2026-08-20 07:29:30 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: syncode/identity#5