4.7 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | |||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 07-user-plugin-and-authentication | 04 | auth |
|
|
|
|
|
|
|
|
75min | 2026-09-22 |
Phase 7 Plan 04: Personal tokens and locale Summary
Personal API tokens can be minted, listed, and revoked, and me/locale stays reachable while the password-change lock returns 423 everywhere else on /_fonoteka/api/v1.
Performance
- Duration: 75 min
- Started: 2026-09-22T14:50:00Z
- Completed: 2026-09-22T16:05:00Z
- Tasks: 3
- Files modified: 16
Accomplishments
MintPersonalTokenreturns aninv_secret whose sha256 hex matchesTokenGuard. Revoke stampsrevoked_at.POST /tokensrejects a scope outsideread,write, andaibefore insert.GET /tokensomits the secret.DELETE /tokens/{id}is owner-scoped.GET/PUT /me/localepersistploren. A locked user can still change locale and gets 423 on genres.- The five routes replay as
status: ported. The corpus is 7 ported and 147 pending out of 154.
Task Commits
- Task 1: Mint and revoke —
3c53bf8infonoteka.go - Task 2: Token and locale HTTP —
58fcb45infonoteka.go - Task 3: Exempt-route proof and parity flip —
fa95534infonoteka.go
Files Created/Modified
plugins/golem15/fonoteka/classes/auth/api_token_manager.go— mint and revokeplugins/golem15/fonoteka/controllers/api/token_api_controller.go— store, index, destroyplugins/golem15/fonoteka/controllers/api/me_locale_controller.go— show and updateplugins/golem15/fonoteka/routes.go— locale middleware placementparity/manifest.yaml— five routes marked ported
Decisions Made
The captured POST /tokens body was a debug HTML 500 from an empty name. The Go handler returns 422 {"error":"Validation failed","errors":{"name":["The name field is required."]}}, and the fixture now records that.
GET /tokens was a capture of a live parity-mcp row. Replay uses the genres seed token Parity MCP with scope read, and the fixture follows that seed.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Nil validation map panicked on a bad scope
- Found during: Task 2
- Issue:
lagoon.Validatereturns a nil map whennameis valid, and assigningerrs["scopes"]panicked into an opaque 500. - Fix: Allocate the map before recording the scope error.
- Files modified:
controllers/api/token_api_controller.go - Committed in:
58fcb45
2. [Rule 1 - Bug] created_at used a Z suffix
- Found during: Task 3
- Issue: Tide accepts only Carbon
+00:00timestamps.time.RFC3339emitsZ. - Fix: Format token timestamps as
2006-01-02T15:04:05-07:00. - Files modified:
controllers/api/token_api_controller.go - Committed in:
fa95534
Total deviations: 2 auto-fixed Impact on plan: Bad scopes stay 422. Token timestamps match the parity normalizer.
Issues Encountered
None
User Setup Required
None - no external service configuration required.
Next Phase Readiness
Ready for 07-05, which starts by recording the isolated PHP instance. AUTH-03 and AUTH-04 stay unchecked until the phase requirement is signed off.
Self-Check: PASSED
TestMintPersonalToken,TestTokenApi,TestMeLocale, andTestRequirePasswordChangeExemptSetpassed.go test ./parity/ -run 'TestParityCorpus|TestParityContract'passed with 7 ported routes.- Commits
3c53bf8,58fcb45, andfa95534are onfonoteka.gomaster.