# Phase 14.1: OAuth identities and fonoteka me routes - Discussion Log > **Audit trail only.** Do not use as input to planning, research, or execution agents. > Decisions are captured in CONTEXT.md. This log preserves the alternatives considered. **Date:** 2026-10-04 **Phase:** 14.1-oauth-identities-and-fonoteka-me-routes **Areas discussed:** where the identity table lives, token columns and import, parity case coverage, social-login-only users at cutover The scout found two things before the discussion: - `GET /api/v1/fonoteka/me` is already served in Go. Its only gap is that `collection_ids` is `[]` where PHP returns `null` for an unrestricted token. This is decided by the PHP contract and was not asked. - Go has no model or migration for `golem15_user_oauth_identities`. --- ## Where the identity table lives | Option | Description | Selected | |--------|-------------|----------| | sm-user-plugin | Mirrors PHP, where Golem15.User owns the table; additive change | ✓ | | fonoteka plugin | Leaves the shared plugin untouched, but the table sits in the wrong plugin | | The user asked what the handlers are for. They back Settings → Connected accounts in the Nuxt app, which lists linked Google, Facebook and GitHub logins and lets the user disconnect them. Unlinking the last one returns 409. | Option | Description | Selected | |--------|-------------|----------| | fonoteka plugin | Same as PHP | | | user plugin API | Reusable handlers that fonoteka mounts at its prefix | ✓ | | Option | Description | Selected | |--------|-------------|----------| | User plugin lang, same text | New key in the user plugin with identical EN/PL text | ✓ | | Host passes the message | The mount supplies the message key | | | Option | Description | Selected | |--------|-------------|----------| | Mount option, default the three | google/facebook/github by default; the host can narrow or extend | ✓ | | Hard-coded three | Matches PHP exactly | | ## Token columns and import | Option | Description | Selected | |--------|-------------|----------| | Full PHP column set | Encrypted tokens, jsonb profile_data, both unique indexes | ✓ | | Full columns, tokens nulled at import | Drop the stored provider tokens at import | | | Only what list/unlink need | Minimal columns | | | Option | Description | Selected | |--------|-------------|----------| | No, Phase 15 writes the import mapper | HasWinterImport does not exist yet | ✓ | | Yes, note the transforms now | Docs only | | ## Parity case coverage Identity cases to record (multi-select): list with linked rows ✓, unlink 204 and last-method 409 ✗, foreign vs missing 404 ✗, unknown provider and 401 ✗. | Option | Description | Selected | |--------|-------------|----------| | Add unrestricted-token case (/me) | `collection_ids: null` case | ✓ | | Also scope variants | Read-only and revoked tokens | | | Option | Description | Selected | |--------|-------------|----------| | Go tests ported from the PHP tests | Covers the unselected behaviours in the final unit-test plan | ✓ | | Keep only what's recorded | | | ## Social-login-only users at cutover | Option | Description | Selected | |--------|-------------|----------| | Flag for the Phase 15 preflight | Count OAuth-only users in the dump; give them a password first, or schedule a social login phase | ✓ | | Accept, nobody uses it | | | | Pull social login into scope | Big scope jump | | ## Claude's Discretion - The shape of the exported sm-user-plugin API and how fonoteka mounts it - Where the throttle for `throttle:10,1` is declared - ISO-8601 formatting that matches Laravel's `toIso8601String()` - Plan split (unit tests come last; the plan count is confirmed first) - README and docs updates ## Deferred Ideas - Social login port (its own phase; the Phase 15 preflight decides the urgency) - Winter-import mapper for the identities table (Phase 15)