Skip to content

feat(auth)!: drop better-auth and the legacy permission tables (RFC v3 Phase 6) - #93

Open
BIA3IA wants to merge 1 commit into
mainfrom
feat/idp-phase6-cleanup
Open

BIA3IA wants to merge 1 commit into
mainfrom
feat/idp-phase6-cleanup

Conversation

@BIA3IA

@BIA3IA BIA3IA commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

RFC v3 Phase 6 (§9.3, §9.4, §13) for the backend. Since Phase 5, roles, group admins and Telegram links live in the IdP, so this PR removes the backend's own login and the tables behind it.

Removed

  • better-auth: email OTP, passkeys, the Telegram link plugin, the /api/auth/* routes and their CORS, the OTP email template, and the better-auth / @better-auth/* dependencies.
  • Settings: BETTER_AUTH_SECRET, PUBLIC_URL and TRUSTED_ORIGINS. They are no longer read, so leaving them set is harmless.
  • Tables (migration 0027_idp_phase6_cleanup): tg_permissions, tg_group_admins, tg_link and auth_*.
  • Legacy tg_grants: not migrated (§4 decision 6). tg_grants_v2 is renamed to tg_grants, together with its sequence, index and constraints.
  • SDK exports: AUTH_PATH, USER_ROLE and TelegramPlugin. No consumer imports them (I checked telegram, admin and web).
  • Scripts: idp:export / idp:reconcile (they read tg_permissions) and seed:user (better-auth). Also the tg_link cleanup cron.

Changed

  • Author columns (§9.4): the columns that referenced tg_permissions (web_* and common_group_labels) become legacy_created_by_tg_id / legacy_modified_by_tg_id.
    • They are renamed, not dropped, so the old Telegram IDs stay for history.
    • The foreign keys are removed.
    • The *_creator_check constraints now require legacy_created_by_tg_id or created_by_sub.
    • New writes set only *_by_sub. A modification clears the legacy modifier.
  • Freshman writes no longer accept modifiedBy. The admin dashboard never sent it.
  • Grants read from a single table. key, source and grantedBy stay in the output, now always idp:<id>, "idp" and null, and marked @deprecated. Today's admin uses them, so it keeps working at runtime until it updates the SDK.

⚠️ Before merging: backup

Merging is deploying. Docker CI pushes backend:latest and Flux deploys its new digest by itself (polinetwork-cd/clusters/k3s/apps/backend.yaml). Migrations run when the backend starts (src/db/db.ts), so the first pod running this image deletes the tables, a few minutes after the merge. Rolling back the image does not bring them back, and the previous image no longer works once the migration has run.

  1. Take a full dump of the production database, from wherever you can reach Postgres (e.g. the dbpg route):
    pg_dump --format=custom --file=backend-pre-phase6-$(date +%F).dump \
      -h <host> -p <port> -U <user> <db>
    pg_restore --list backend-pre-phase6-*.dump | grep -E 'tg_permissions|tg_group_admins|tg_link|tg_grants|auth_users'
  2. Store the dump somewhere safe (e.g. Azure Blob). It is the archive of the legacy grants required by decision 6.
  3. Re-enter any still-needed legacy grants by hand after the deploy: they are not migrated.

Rollback: restore the dump and redeploy the previous image.

Order

  1. Backup (above).
  2. Merge this PR. Flux deploys it.
  3. Check the pod ([DB] Migration completed).
  4. Merge feat(backend): close public access and allow only in-cluster callers polinetwork-cd#28, which removes the Ingress and the old env vars and adds the NetworkPolicy. It must come after, because the current image still requires BETTER_AUTH_SECRET.

Release

This is a breaking change for the SDK (exports removed), so it should release 3.0.0.

Verification

  • bun run typecheck, bun run biome ci ., bun run build and bun run build:npm: OK.
  • bun run test with the Postgres integration suites enabled (SEED_TEST_DB_PORT, FRESHMAN_TEST_DB_PORT): 249 passed, 1 skipped (after rebasing onto feat(azure): let the dashboard change member numbers and choose the new address #70).
  • Migration on a throwaway Postgres 18:
    1. Seeded with main (8 tg_permissions, 12 tg_group_admins, 1 legacy grant, 11 tg_grants_v2, legacy-authored labels and web content, a better-auth user with a tg_link).
    2. Started this branch. Result:
      • the legacy tables are gone;
      • the 11 IdP grants are in tg_grants and inserts continue from the sequence;
      • the legacy authors are kept in legacy_*_tg_id;
      • no foreign key is left dangling.
  • After the migration, drizzle-kit generate reports "No schema changes".
  • The freshman integration fixture now applies only the migrations before 0026. Before, it applied "all but 0026", which would have run 0027 first.

Not in this PR

  • tg_audit_log.admin_id: the bot still reads it until it updates the SDK.
  • tg_test / web_test: tg_test is the startup DB check.

@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 09c589a9-7f2d-4d99-b0f3-c6e3a8c071db
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…3 Phase 6)

Roles, group admins and Telegram links live in the IdP since Phase 5,
so the backend's own login and the tables behind it go:

- better-auth (email OTP, passkeys, Telegram link plugin), its
  /api/auth routes and CORS, the OTP email, and the BETTER_AUTH_SECRET,
  PUBLIC_URL and TRUSTED_ORIGINS settings
- tg_permissions, tg_group_admins, tg_link and auth_* (migration 0027)
- the legacy tg_grants table, not migrated (decision 6); tg_grants_v2
  takes its name
- the AUTH_PATH, USER_ROLE and TelegramPlugin exports
- the idp:export / idp:reconcile migration tooling and seed:user

The author columns that referenced tg_permissions keep the old Telegram
IDs as legacy_created_by_tg_id / legacy_modified_by_tg_id, without the
foreign keys (§9.4). Freshman writes no longer accept `modifiedBy`.
Grants still return `key`, `source` and `grantedBy`, now constant, so
dashboards built against SDK v2 keep working.

BREAKING CHANGE: the SDK no longer exports AUTH_PATH, USER_ROLE and
TelegramPlugin, the backend serves no /api/auth, and migration 0027
drops the legacy tables on startup. Back them up before deploying.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant