docs(14.1-02): complete OAuth identities unit-test plan
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -81,7 +81,7 @@ Requirements for v1 (the Płytarium port). Each maps to roadmap phases. "User" b
|
|||||||
- [x] **API-06**: Per-user and per-org Discogs and AI credentials CRUD with encrypted storage, org-lock flag, and env-to-org-to-user resolution (the live ai-credential/test and discogs-credential/test routes are Phase 14, with INTG-01 and INTG-02)
|
- [x] **API-06**: Per-user and per-org Discogs and AI credentials CRUD with encrypted storage, org-lock flag, and env-to-org-to-user resolution (the live ai-credential/test and discogs-credential/test routes are Phase 14, with INTG-01 and INTG-02)
|
||||||
- [x] **API-07**: Onboarding, public and invitation inspection routes, including the anonymous collection public-token views (public/{token}, its albums and album detail), with their public rate-limit buckets
|
- [x] **API-07**: Onboarding, public and invitation inspection routes, including the anonymous collection public-token views (public/{token}, its albums and album detail), with their public rate-limit buckets
|
||||||
- [x] **API-08**: Feedback submissions, widget config and the per-user hide preference from the stack feedback plugin (sitemap dropped for this application, D-14)
|
- [x] **API-08**: Feedback submissions, widget config and the per-user hide preference from the stack feedback plugin (sitemap dropped for this application, D-14)
|
||||||
- [ ] **API-09**: All 154 routes are registered on the correct groups with identical paths, methods, status codes and bodies
|
- [x] **API-09**: All 154 routes are registered on the correct groups with identical paths, methods, status codes and bodies
|
||||||
|
|
||||||
### Background jobs (JOBS)
|
### Background jobs (JOBS)
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ Requirements for v1 (the Płytarium port). Each maps to roadmap phases. "User" b
|
|||||||
- [x] **QA-02**: A replay-and-diff harness runs fixtures against the Go backend with a normalizer for nondeterministic fields and assertions for the parity classes (nil vs [], date formats, tri-state booleans, envelopes, conditional keys)
|
- [x] **QA-02**: A replay-and-diff harness runs fixtures against the Go backend with a normalizer for nondeterministic fields and assertions for the parity classes (nil vs [], date formats, tri-state booleans, envelopes, conditional keys)
|
||||||
- [x] **QA-03**: go vet and go test ./... are green at every commit; each phase ends with a unit-test plan; integration tests use testcontainers Postgres
|
- [x] **QA-03**: go vet and go test ./... are green at every commit; each phase ends with a unit-test plan; integration tests use testcontainers Postgres
|
||||||
- [x] **QA-04**: The first vertical slice (GET /_fonoteka/api/v1/genres) passes the parity diff end to end before further kernel abstraction
|
- [x] **QA-04**: The first vertical slice (GET /_fonoteka/api/v1/genres) passes the parity diff end to end before further kernel abstraction
|
||||||
- [ ] **QA-05**: Cutover: the parity harness is green on all 154 routes and vue-fonoteka-app and fonoteka-mcp run unchanged against the Go backend
|
- [x] **QA-05**: Cutover: the parity harness is green on all 154 routes and vue-fonoteka-app and fonoteka-mcp run unchanged against the Go backend
|
||||||
|
|
||||||
### Documentation (DOCS)
|
### Documentation (DOCS)
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| API-06 | Phase 13 | Complete |
|
| API-06 | Phase 13 | Complete |
|
||||||
| API-07 | Phase 13 | Complete |
|
| API-07 | Phase 13 | Complete |
|
||||||
| API-08 | Phase 14 | Complete |
|
| API-08 | Phase 14 | Complete |
|
||||||
| API-09 | Phase 15 | Pending |
|
| API-09 | Phase 15 | Complete |
|
||||||
| JOBS-01 | Phase 11 | Gaps Found |
|
| JOBS-01 | Phase 11 | Gaps Found |
|
||||||
| JOBS-02 | Phase 14 | Complete |
|
| JOBS-02 | Phase 14 | Complete |
|
||||||
| JOBS-03 | Phase 14 | Complete |
|
| JOBS-03 | Phase 14 | Complete |
|
||||||
@@ -242,7 +242,7 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| QA-02 | Phase 2 | Complete |
|
| QA-02 | Phase 2 | Complete |
|
||||||
| QA-03 | Phase 2 | Complete |
|
| QA-03 | Phase 2 | Complete |
|
||||||
| QA-04 | Phase 3 | Complete |
|
| QA-04 | Phase 3 | Complete |
|
||||||
| QA-05 | Phase 15 | Pending |
|
| QA-05 | Phase 15 | Complete |
|
||||||
| DOCS-01 | Phase 11.1 | Complete |
|
| DOCS-01 | Phase 11.1 | Complete |
|
||||||
| DOCS-02 | Phase 11.1 | Complete |
|
| DOCS-02 | Phase 11.1 | Complete |
|
||||||
| DOCS-03 | Phase 11.1 | Complete |
|
| DOCS-03 | Phase 11.1 | Complete |
|
||||||
|
|||||||
@@ -798,7 +798,7 @@ Plans:
|
|||||||
3. `GET /api/v1/fonoteka/me` matches the PHP response for fonoteka-mcp token callers.
|
3. `GET /api/v1/fonoteka/me` matches the PHP response for fonoteka-mcp token callers.
|
||||||
4. All three manifest entries flip from `pending` to ported with recorded PHP cases, leaving zero pending routes.
|
4. All three manifest entries flip from `pending` to ported with recorded PHP cases, leaving zero pending routes.
|
||||||
|
|
||||||
**Plans:** 1/2 plans executed
|
**Plans:** 2/2 plans executed
|
||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
|
|
||||||
@@ -806,7 +806,7 @@ Plans:
|
|||||||
- [x] 14.1-01-PLAN.md — Model, migration, exported Index/Destroy, JWT mount, `/me` null, D-10 recording and manifest flip
|
- [x] 14.1-01-PLAN.md — Model, migration, exported Index/Destroy, JWT mount, `/me` null, D-10 recording and manifest flip
|
||||||
|
|
||||||
**Wave 2** *(blocked on Wave 1 completion)*
|
**Wave 2** *(blocked on Wave 1 completion)*
|
||||||
- [ ] 14.1-02-PLAN.md — Unit tests last: OAuthIdentityApiTest port, migration, MeToken null, secret-leak, corpus 175/175/0
|
- [x] 14.1-02-PLAN.md — Unit tests last: OAuthIdentityApiTest port, migration, MeToken null, secret-leak, corpus 175/175/0
|
||||||
|
|
||||||
### Phase 15: Cutover
|
### Phase 15: Cutover
|
||||||
|
|
||||||
@@ -848,7 +848,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
|
|||||||
| 12. Płytarium API — Collections and Albums | 5/5 | Complete | 2026-10-02 |
|
| 12. Płytarium API — Collections and Albums | 5/5 | Complete | 2026-10-02 |
|
||||||
| 13. Płytarium API — wishlist, notifications, CSV, credentials, public routes | 6/6 | In Progress| |
|
| 13. Płytarium API — wishlist, notifications, CSV, credentials, public routes | 6/6 | In Progress| |
|
||||||
| 14. Domain jobs and external integrations | 6/6 | In Progress| |
|
| 14. Domain jobs and external integrations | 6/6 | In Progress| |
|
||||||
| 14.1. OAuth identities and fonoteka me routes (INSERTED) | 1/2 | In Progress| |
|
| 14.1. OAuth identities and fonoteka me routes (INSERTED) | 2/2 | In Progress| |
|
||||||
| 15. Cutover | 0/TBD | Not started | - |
|
| 15. Cutover | 0/TBD | Not started | - |
|
||||||
|
|
||||||
## Backlog
|
## Backlog
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ milestone: v1.0
|
|||||||
current_phase: "14.1"
|
current_phase: "14.1"
|
||||||
current_phase_name: OAuth identities and fonoteka me routes
|
current_phase_name: OAuth identities and fonoteka me routes
|
||||||
status: executing
|
status: executing
|
||||||
stopped_at: Completed 14.1-01-PLAN.md
|
stopped_at: Completed 14.1-02-PLAN.md
|
||||||
last_updated: "2026-10-05T19:24:46.112Z"
|
last_updated: "2026-10-05T19:38:03.055Z"
|
||||||
last_activity: 2026-10-05
|
last_activity: 2026-10-05
|
||||||
last_activity_desc: Completed 14.1-01-PLAN.md
|
last_activity_desc: Completed 14.1-02-PLAN.md
|
||||||
state_head: c3bbbcbb9f7e247c353e262d0fec8126fac78e04
|
state_head: 0d1b5caf3dff811c11abd6c010d10f68d30fe3bf
|
||||||
progress:
|
progress:
|
||||||
total_phases: 22
|
total_phases: 22
|
||||||
completed_phases: 11
|
completed_phases: 11
|
||||||
total_plans: 125
|
total_plans: 125
|
||||||
completed_plans: 124
|
completed_plans: 125
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -29,11 +29,11 @@ See: .planning/PROJECT.md (updated 2026-09-16)
|
|||||||
## Current Position
|
## Current Position
|
||||||
|
|
||||||
Phase: 14.1 (OAuth identities and fonoteka me routes) — EXECUTING
|
Phase: 14.1 (OAuth identities and fonoteka me routes) — EXECUTING
|
||||||
Plan: 1 of 2 complete
|
Plan: 2 of 2 complete
|
||||||
Status: Executing Phase 14.1; next is 14.1-02 unit tests
|
Status: Phase 14.1 plans complete; next is /gsd-verify-work 14.1
|
||||||
Last activity: 2026-10-05 — Completed 14.1-01-PLAN.md
|
Last activity: 2026-10-05 — Completed 14.1-02-PLAN.md
|
||||||
|
|
||||||
Progress: [█████░░░░░] 50%
|
Progress: [██████████] 100%
|
||||||
|
|
||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
@@ -178,6 +178,7 @@ Progress: [█████░░░░░] 50%
|
|||||||
| Phase 12.1 P04 | 32min | 4 tasks | 35 files |
|
| Phase 12.1 P04 | 32min | 4 tasks | 35 files |
|
||||||
| Phase 12.1 P05 | 103min | 3 tasks | 56 files |
|
| Phase 12.1 P05 | 103min | 3 tasks | 56 files |
|
||||||
| Phase 14.1 P01 | 90 | 4 tasks | 20 files |
|
| Phase 14.1 P01 | 90 | 4 tasks | 20 files |
|
||||||
|
| Phase 14.1 P02 | 8 min | 3 tasks | 3 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -561,6 +562,9 @@ Recent decisions affecting current work:
|
|||||||
- [Phase 12.1]: 12.1-04: Organisation gained the Go relation field Members (no column) because the relation manager requires the relation on the owner model
|
- [Phase 12.1]: 12.1-04: Organisation gained the Go relation field Members (no column) because the relation manager requires the relation on the owner model
|
||||||
- [Phase 12.1]: 12.1-04: the organisation members manager links only users without an organisation; a user moves by unlink then link, or through the user form's organisation field
|
- [Phase 12.1]: 12.1-04: the organisation members manager links only users without an organisation; a user moves by unlink then link, or through the user form's organisation field
|
||||||
- [Phase 12.1]: 12.1-04: nothing was pushed; the fonoteka.go pointer names an unpublished plugin commit, so the order is framework tag, then sm-user-plugin (plan 05 Task 3), then fonoteka.go
|
- [Phase 12.1]: 12.1-04: nothing was pushed; the fonoteka.go pointer names an unpublished plugin commit, so the order is framework tag, then sm-user-plugin (plan 05 Task 3), then fonoteka.go
|
||||||
|
- [Phase 14.1]: sessionApp does not phrasebook.Activate; EN/PL 409 tests activate catalogs and set locale with towel.WithLocale — sessionApp Boots the plugin only; Get would return the raw last_method_blocked key
|
||||||
|
- [Phase 14.1]: Unique (provider, provider_id) is table-global; EN/PL 409 seeds use provider_id fb-only-<locale> — oauth_identities_provider_identity_unique is not per-user
|
||||||
|
- [Phase 14.1]: Task 3 needed no parity_test.go change: 14.1-01 already set expectedPortedRoutes 175 and rewrote assertPortedMismatch — Corpus already recorded 175/175 passing 175 failing 0 unrecorded 0 pending 0
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -612,6 +616,6 @@ Items acknowledged and carried forward from previous milestone close:
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-10-05T19:24:45.572Z
|
Last session: 2026-10-05T19:38:02.502Z
|
||||||
Stopped at: Completed 14.1-01-PLAN.md
|
Stopped at: Completed 14.1-02-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
@@ -0,0 +1,212 @@
|
|||||||
|
---
|
||||||
|
phase: 14.1-oauth-identities-and-fonoteka-me-routes
|
||||||
|
plan: 02
|
||||||
|
subsystem: testing
|
||||||
|
tags: [oauth-identities, sm-user-plugin, me-token, parity, gormigrate, lagoon.Encrypted, winter-404, phrasebook, throttle]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 14.1-oauth-identities-and-fonoteka-me-routes
|
||||||
|
provides: "Host-mounted OAuthIdentitiesIndex/Destroy, migration 202610050001, D-09 MeToken collection_ids JSON null, three manifest routes ported, expectedPortedRoutes 175"
|
||||||
|
- phase: 07-user-plugin-and-authentication
|
||||||
|
provides: "sessionApp/insertUser, jwt.auth JSON 401, lang YAML, dedicatedDB"
|
||||||
|
provides:
|
||||||
|
- "OAuthIdentityApiTest.php port: 204 sibling remains, last-method 409 EN/PL, Winter HTML 404 byte-identical for missing/foreign/unknown, 401 on GET and DELETE /google"
|
||||||
|
- "gormigrate up/down for golem15_user_oauth_identities (jsonb profile_data, both unique indexes, CASCADE FK)"
|
||||||
|
- "MeToken nil CollectionIDs serializes as JSON null; scopes stay []"
|
||||||
|
- "Encrypted token/profile_data secret-leak assertions on GET list"
|
||||||
|
- "TestParityCorpus recorded 175/175 passing 175 failing 0 unrecorded 0 pending 0"
|
||||||
|
affects: [15-cutover (zero pending routes), verify-work 14.1]
|
||||||
|
|
||||||
|
actuals:
|
||||||
|
tokens: 4200
|
||||||
|
tasks: 3
|
||||||
|
commits: 3
|
||||||
|
plan_head_before: 0d1b5caf3dff811c11abd6c010d10f68d30fe3bf
|
||||||
|
plugin_repo_head_after: f0d3b8b21d3d11bcf5cbf288f715bc1ec94f9ebe
|
||||||
|
app_repo_head_after: fbe346950ae2715939c2bac209a51ca43fa75883
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "409 locale tests call phrasebook.Activate because sessionApp Boots the plugin without activating catalogs"
|
||||||
|
- "oauth_identities_provider_identity_unique is global (provider, provider_id), not per-user — locale cases must use distinct provider_ids"
|
||||||
|
- "Secret-leak Index assertions refuse plaintext, Encrypted JSON keys, and the [redacted] marshal literal"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- ../fonoteka.go/plugins/golem15/user/updates/oauth_identities_test.go
|
||||||
|
modified:
|
||||||
|
- ../fonoteka.go/plugins/golem15/user/oauth_identities_test.go
|
||||||
|
- ../fonoteka.go/plugins/golem15/fonoteka/controllers/api/me_token_controller_test.go
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "sessionApp does not phrasebook.Activate; EN/PL 409 tests activate catalogs and set locale with towel.WithLocale"
|
||||||
|
- "Unique (provider, provider_id) is table-global; EN/PL 409 seeds use provider_id fb-only-<locale>"
|
||||||
|
- "Task 3 needed no parity_test.go change: 14.1-01 already set expectedPortedRoutes 175 and rewrote assertPortedMismatch"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Destroy tests inject WriteNotFound that copies Winter HTML 404 bytes so missing, foreign, and unknown providers stay indistinguishable"
|
||||||
|
- "DATA-07 list tests seed lagoon.NewEncrypted after PublishEncryptionKeys and assert the Index body never names token columns"
|
||||||
|
|
||||||
|
requirements-completed: [API-09, QA-05, HTTP-01, HTTP-03, DATA-02, DATA-07, I18N-01]
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
- id: D1
|
||||||
|
description: "Unlink 204 keeps the sibling row; last remaining identity returns 409 EN and PL last_method_blocked texts, including when the account has a password"
|
||||||
|
requirement: I18N-01
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/user#TestOAuthIdentitiesDestroyNoContentKeepsSibling"
|
||||||
|
status: pass
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/user#TestOAuthIdentitiesDestroyLastMethodBlockedENAndPL"
|
||||||
|
status: pass
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/user#TestOAuthIdentitiesDestroyLastMethodBlockedWithPassword"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D2
|
||||||
|
description: "Missing, foreign, and unknown-provider DELETE return byte-identical Winter HTML 404; unauthenticated GET and DELETE /google return 401"
|
||||||
|
requirement: HTTP-01
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/user#TestOAuthIdentitiesDestroyWinter404BodiesAreByteIdentical"
|
||||||
|
status: pass
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/user#TestOAuthIdentitiesUnauthorizedOnGoogle"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D3
|
||||||
|
description: "Identity routes exist on the JWT group only; DELETE middleware includes throttle:10,1; token group never lists oauth-identities"
|
||||||
|
requirement: HTTP-03
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/fonoteka#TestOAuthTokenSurfaceIsolationCoverage/test_oauth_identity_routes_exist_on_jwt_surface_only"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D4
|
||||||
|
description: "oauth-identities migration migrates up and rolls back: table, jsonb profile_data, both unique indexes, cascade FK present after up and absent after down"
|
||||||
|
requirement: DATA-02
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/user/updates#TestOAuthIdentitiesMigration"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D5
|
||||||
|
description: "GET list with seeded Encrypted tokens never contains plaintext, access_token/refresh_token/profile_data keys, or [redacted]"
|
||||||
|
requirement: DATA-07
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/user#TestOAuthIdentitiesIndexDoesNotLeakEncryptedTokensOrProfileData"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D6
|
||||||
|
description: "Unrestricted /me emits collection_ids as JSON null and scopes as []; TestParityCorpus is recorded 175/175 passing 175 failing 0 unrecorded 0 pending 0"
|
||||||
|
requirement: API-09
|
||||||
|
verification:
|
||||||
|
- kind: unit
|
||||||
|
ref: "plugins/golem15/fonoteka/controllers/api#TestMeTokenHandlerNilScopesSerializeAsEmptyArrayAndCollectionIDsAsJSONNull"
|
||||||
|
status: pass
|
||||||
|
- kind: e2e
|
||||||
|
ref: "parity#TestParityCorpus recorded 175/175 passing 175 failing 0 unrecorded 0 pending 0"
|
||||||
|
status: pass
|
||||||
|
human_judgment: false
|
||||||
|
- id: D7
|
||||||
|
description: "QA-05 consumers stay frozen: Nuxt Settings → Connected accounts list/unlink and fonoteka-mcp me() against Go"
|
||||||
|
requirement: QA-05
|
||||||
|
verification: []
|
||||||
|
human_judgment: true
|
||||||
|
rationale: "Plan human-check is a live Nuxt and MCP session against the Go backend; the corpus and unit tests cannot sign that consumers are unchanged"
|
||||||
|
|
||||||
|
duration: 8min
|
||||||
|
completed: 2026-10-05
|
||||||
|
status: complete
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 14.1 Plan 02: OAuth identities unit tests Summary
|
||||||
|
|
||||||
|
**OAuthIdentityApiTest.php ported (204, EN/PL 409, Winter 404s, 401 /google), migration up/down, `/me` collection_ids JSON null, Encrypted secret-leak, corpus 175/175/0**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 8 min
|
||||||
|
- **Started:** 2026-10-05T19:28:51Z
|
||||||
|
- **Completed:** 2026-10-05T19:37:04Z
|
||||||
|
- **Tasks:** 3
|
||||||
|
- **Files modified:** 3
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- Plugin tests prove unlink 204 keeps the sibling row, last-method 409 EN and PL match `golem15.user::lang.oauth.last_method_blocked` (including when the account has a password), missing/foreign/unknown Winter HTML 404 bodies are byte-identical, and both identity routes return 401 without a JWT on `/google`.
|
||||||
|
- `updates/oauth_identities_test.go` migrates `golem15_user_oauth_identities` up and down on real Postgres: jsonb `profile_data`, both unique indexes, CASCADE FK.
|
||||||
|
- Rewritten MeToken nil test requires `"collection_ids":null` and treats `"scopes":null` as failure.
|
||||||
|
- GET list with `lagoon.NewEncrypted` tokens never leaks plaintext, Encrypted JSON keys, or `[redacted]`.
|
||||||
|
- `TestParityCorpus` prints `recorded 175/175 passing 175 failing 0 unrecorded 0 pending 0`.
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Port OAuthIdentityApiTest.php — 204, EN/PL 409, Winter 404s, 401 /google, jwt-only surfaces** — `026848f` (sm-user-plugin test). phase08 jwt-only + `throttle:10,1` already shipped in 14.1-01; no fonoteka.go commit.
|
||||||
|
2. **Task 2: Migration up/down, MeToken null collection_ids, secret-leak** — `f0d3b8b` (sm-user-plugin test), `fbe3469` (fonoteka.go test + gitlink)
|
||||||
|
3. **Task 3: TestParityCorpus 175/175/0** — no code commit (`expectedPortedRoutes = 175` and rewritten `assertPortedMismatch` already on disk from 14.1-01)
|
||||||
|
|
||||||
|
**Plan metadata:** this SUMMARY commit
|
||||||
|
|
||||||
|
_Note: TDD was not applicable for this plan._
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `plugins/golem15/user/oauth_identities_test.go` — D-11 matrix plus DATA-07 secret-leak
|
||||||
|
- `plugins/golem15/user/updates/oauth_identities_test.go` — dedicatedDB gormigrate up/down
|
||||||
|
- `plugins/golem15/fonoteka/controllers/api/me_token_controller_test.go` — D-09 `"collection_ids":null`
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- **phrasebook.Activate in 409 tests:** `sessionApp` Boots the plugin only; catalogs must be activated for EN/PL `last_method_blocked` lookup.
|
||||||
|
- **Global unique (provider, provider_id):** locale cases seed `fb-only-<locale>` so they do not collide on `oauth_identities_provider_identity_unique`.
|
||||||
|
- **Task 3 verification-only:** corpus constants and mismatch helper were already 175/ported after 14.1-01.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 3 - Blocking] EN/PL 409 seed collided on provider_identity unique**
|
||||||
|
- **Found during:** Task 1 (EN/PL 409)
|
||||||
|
- **Issue:** Both locales used `provider_id` `fb-only`; the second insert failed `oauth_identities_provider_identity_unique`.
|
||||||
|
- **Fix:** Seed `fb-only-` plus locale. Unique is global, not per-user.
|
||||||
|
- **Files modified:** `../fonoteka.go/plugins/golem15/user/oauth_identities_test.go`
|
||||||
|
- **Verification:** `TestOAuthIdentitiesDestroyLastMethodBlockedENAndPL` PASS
|
||||||
|
- **Committed in:** `026848f` (Task 1)
|
||||||
|
|
||||||
|
**2. [Rule 2 - Missing Critical] 409 tests must activate phrasebook**
|
||||||
|
- **Found during:** Task 1 (EN/PL 409)
|
||||||
|
- **Issue:** `sessionApp` does not call `phrasebook.Activate`; Get returned the raw key.
|
||||||
|
- **Fix:** `phrasebook.Activate(app, []*Plugin{{}})` plus `towel.WithLocale`.
|
||||||
|
- **Files modified:** `../fonoteka.go/plugins/golem15/user/oauth_identities_test.go`
|
||||||
|
- **Verification:** EN and PL bodies equal the lang YAML strings
|
||||||
|
- **Committed in:** `026848f` (Task 1)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 2 auto-fixed (1 blocking, 1 missing critical)
|
||||||
|
**Impact on plan:** Both needed so 409 tests fail when lang YAML or locale wiring break. No scope creep.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
- First EN/PL 409 run failed on the unique index (deviation 1). GORM "record not found" logs on Winter 404 branches are expected `First()` misses.
|
||||||
|
- Task 3 ran `go vet` then `TestParityCorpus`; verbose coverage line `recorded 175/175 passing 175 failing 0 unrecorded 0 pending 0`. No fixture re-record.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None - no external service configuration required.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Phase 14.1 plans are both summarized; ready for `/gsd-verify-work 14.1`. Human-check D7 (Nuxt Connected accounts, fonoteka-mcp `me()`) remains for that step.
|
||||||
|
- Do not push sm-user-plugin or fonoteka.go. Plugin HEAD `f0d3b8b` and app HEAD `fbe3469` are local-only.
|
||||||
|
- `scripts/check-phase14.sh` `EXPECTED_PENDING=3` stays historical.
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 14.1-oauth-identities-and-fonoteka-me-routes*
|
||||||
|
*Completed: 2026-10-05*
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
{
|
{
|
||||||
"number": "14.1",
|
"number": "14.1",
|
||||||
"name": "OAuth identities and fonoteka me routes (INSERTED)",
|
"name": "OAuth identities and fonoteka me routes (INSERTED)",
|
||||||
"status": "pending"
|
"status": "in_progress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"number": "15",
|
"number": "15",
|
||||||
@@ -99,5 +99,5 @@
|
|||||||
"label": "Advance to the next step",
|
"label": "Advance to the next step",
|
||||||
"reason": "Phase 14.1 of 22 · executing"
|
"reason": "Phase 14.1 of 22 · executing"
|
||||||
},
|
},
|
||||||
"updated_at": "2026-10-05T19:04:22.107Z"
|
"updated_at": "2026-10-05T19:37:09.413Z"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user