docs(07-08): complete the avatar bucket publish plan
Serve and Handler now publish the uploads bucket; assembled avatar POST is 200. Record the gap-closure outcome. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -12,6 +12,7 @@ files_modified:
|
|||||||
- ../fonoteka.go/parity/genre_security_test.go
|
- ../fonoteka.go/parity/genre_security_test.go
|
||||||
- ../fonoteka.go/plugins/golem15/user/avatar_test.go
|
- ../fonoteka.go/plugins/golem15/user/avatar_test.go
|
||||||
autonomous: true
|
autonomous: true
|
||||||
|
gap_closure: true
|
||||||
requirements: []
|
requirements: []
|
||||||
user_setup: []
|
user_setup: []
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
---
|
||||||
|
phase: 07-user-plugin-and-authentication
|
||||||
|
plan: 08
|
||||||
|
subsystem: auth
|
||||||
|
tags: [avatar, blob, gocloud, serve, handler]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 07-user-plugin-and-authentication
|
||||||
|
provides: avatar HTTP handlers and attach.OpenBucket/Publish from Phase 5
|
||||||
|
- phase: 05-data-layer-full-fidelity
|
||||||
|
provides: lagoon/attach OpenBucket, Publish, and mem:// support
|
||||||
|
provides:
|
||||||
|
- surf.ServeCommand and app.Handler publish *blob.Bucket before Assemble
|
||||||
|
- assembled Handler JPEG upload/remove proof that does not hand-publish a memblob
|
||||||
|
affects: [phase-7-verification, phase-12-media]
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "OpenBucket + Publish sit next to lagoon.Publish on every HTTP boot path"
|
||||||
|
- "assembled tests set storage.uploads.bucket_url=mem://; unit tests may still publish memblob by hand"
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- surf/serve_test.go
|
||||||
|
- ../fonoteka.go/parity/avatar_assembled_test.go
|
||||||
|
modified:
|
||||||
|
- surf/serve.go
|
||||||
|
- ../fonoteka.go/app/app.go
|
||||||
|
- ../fonoteka.go/parity/migrate_test.go
|
||||||
|
- ../fonoteka.go/parity/genre_security_test.go
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Both CLI serve and in-process Handler must publish *blob.Bucket; unit tests that call attach.Publish themselves cannot stand in for boot"
|
||||||
|
- "Assembled Handler avatar coverage lives in parity/ next to newConfiguredTarget, not in the user plugin package"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Pattern: empty storage.uploads.bucket_url fails boot as loudly as an empty JWT secret"
|
||||||
|
- "Pattern: TestAvatarAssembled boots app.Handler and curls the real routes; TestUploadAvatar stays handler-unit coverage"
|
||||||
|
|
||||||
|
requirements-completed: []
|
||||||
|
|
||||||
|
duration: 25min
|
||||||
|
completed: 2026-09-23
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 7 Plan 08: Avatar bucket publish Summary
|
||||||
|
|
||||||
|
**Serve and Handler open `storage.uploads.bucket_url` and publish `*blob.Bucket` so assembled avatar POST is 200, not an opaque 500.**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 25 min
|
||||||
|
- **Started:** 2026-09-23T08:24:00Z
|
||||||
|
- **Completed:** 2026-09-23T08:49:38Z
|
||||||
|
- **Tasks:** 3
|
||||||
|
- **Files modified:** 6
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- `surf.ServeCommand` opens the uploads bucket after `lagoon.Publish` and publishes it before `Assemble`; an empty URL fails boot.
|
||||||
|
- `app.Handler` does the same so UAT and parity replay match CLI serve.
|
||||||
|
- `testConfig` / `testConfigCORS` set `mem://` so assembled tests boot without a filesystem uploads dir.
|
||||||
|
- `TestAvatarAssembled` registers a user, logs in, POSTs a JPEG through `app.Handler`, then POSTs remove — without calling `attach.Publish` itself.
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
1. **Task 1: Publish the uploads bucket on serve and Handler** — `44900f0` in `summercms.go`, `bc1adf2` in `fonoteka.go`
|
||||||
|
2. **Task 2: Assembled-app avatar upload and remove** — `b91b728` in `fonoteka.go`
|
||||||
|
3. **Task 3: Race gate both modules** — verification only (no code change)
|
||||||
|
|
||||||
|
**Plan metadata:** this docs commit
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `surf/serve.go` — `publishUploads` after `lagoon.Publish`; `defer bucket.Close()`
|
||||||
|
- `surf/serve_test.go` — empty URL fails; `mem://` stores a lookupable `*blob.Bucket`
|
||||||
|
- `../fonoteka.go/app/app.go` — OpenBucket + Publish on the Handler boot path
|
||||||
|
- `../fonoteka.go/parity/migrate_test.go` — `testConfig` sets `mem://` and `/storage/uploads`
|
||||||
|
- `../fonoteka.go/parity/genre_security_test.go` — same keys on `testConfigCORS`
|
||||||
|
- `../fonoteka.go/parity/avatar_assembled_test.go` — JPEG upload/remove against `app.Handler`
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
Avatar 500s were a missing boot-path publish, not a handler bug. Phase 5 shipped `OpenBucket`/`Publish` but never wired them; Phase 7 added HTTP avatar on top. Both serve and Handler must publish, because UAT and corpus replay boot via Handler.
|
||||||
|
|
||||||
|
Assembled proof belongs next to `newConfiguredTarget` so it cannot import `memblob` and call `attach.Publish`. Existing `TestUploadAvatar` / `TestRemoveAvatar` stay as handler-unit coverage.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. Assembled test file location**
|
||||||
|
- **Found during:** Task 2
|
||||||
|
- **Issue:** Plan `files_modified` listed `avatar_test.go`, but that package cannot reach `app.Handler` without a reverse import.
|
||||||
|
- **Fix:** Added `parity/avatar_assembled_test.go` beside `newConfiguredTarget`, which the plan already allowed.
|
||||||
|
- **Verification:** `go test ./parity/ -run TestAvatarAssembled` passed
|
||||||
|
- **Committed in:** `b91b728`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 1 auto-fixed (test placement)
|
||||||
|
**Impact on plan:** Same proof the plan asked for, on the boot path that hid the gap. No scope creep.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None - no external service configuration required.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
UAT blocker closed. `go vet` and `go test -race` are green in both modules. Ready for phase verification — do not auto-advance to Phase 8.
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- Serve empty-URL boot fails; `mem://` publishes a bucket (`go test ./surf/ -run 'TestPublishUploads|TestServe'`)
|
||||||
|
- Assembled JPEG upload 200 + remove clears `has_avatar` (`TestAvatarAssembled`)
|
||||||
|
- `TestUploadAvatar`, `TestRemoveAvatar`, `TestParityCorpus`, `TestUserAPINuxtFlows` green
|
||||||
|
- `go vet ./... && go test ./... -race` green in `summercms.go` and `fonoteka.go` plus nested plugin packages
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 07-user-plugin-and-authentication*
|
||||||
|
*Completed: 2026-09-23*
|
||||||
Reference in New Issue
Block a user