feat(10-02): filter choices and a fully typed admin API proven on the wire
- pact.FilterOptions on the model serves a scope filter's choices; a scope
filter whose model lacks it fails activation (D-27)
- GET /{vendor}/{plugin}/{controller}/filters/{scope}/options answers a
declared scope filter behind the controller permission with localized
{value, label} choices, 404 otherwise
- Every admin route documents a typed success schema, and protected routes
document 401, 403 and 404 (422 on writes); SuccessEnvelope is gone and
logout writes a typed AdminLogoutData
- jsonScalar and fieldContext decode their served shapes
- TestPhase10OpenAPIConformance calls every inventoried route through the
assembled router on PostgreSQL and decodes each body into its documented
type with unknown fields disallowed, checking admin.json's schema ref
- The SPA aliases every new schema type; Tailwind no longer scans the
generated API files, so API changes do not churn boardwalk/dist
This commit is contained in:
@@ -36,10 +36,9 @@ type SuccessMeta struct {
|
||||
LastPage int `json:"last_page,omitempty"`
|
||||
}
|
||||
|
||||
// SuccessEnvelope is the D-10 success envelope.
|
||||
type SuccessEnvelope struct {
|
||||
Data any `json:"data"`
|
||||
Meta SuccessMeta `json:"meta"`
|
||||
// AdminLogoutData is the POST /auth/logout payload.
|
||||
type AdminLogoutData struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// AdminLoginData is the admin login and refresh payload. Bearer transport
|
||||
@@ -139,8 +138,10 @@ func AdminLang() {}
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[AdminLogoutData]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /auth/logout [post]
|
||||
func AdminLogout() {}
|
||||
|
||||
@@ -152,6 +153,8 @@ func AdminLogout() {}
|
||||
// @Security BackendBearer
|
||||
// @Success 200 {object} Envelope[AdminProfile]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /auth/me [get]
|
||||
func AdminMe() {}
|
||||
|
||||
@@ -164,6 +167,7 @@ func AdminMe() {}
|
||||
// @Success 200 {object} Envelope[[]NavigationEntry]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /navigation [get]
|
||||
func AdminNavigation() {}
|
||||
|
||||
@@ -173,9 +177,10 @@ func AdminNavigation() {}
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[[]SettingsEntry]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /settings [get]
|
||||
func AdminSettingsList() {}
|
||||
|
||||
@@ -186,7 +191,7 @@ func AdminSettingsList() {}
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param code path string true "Settings code"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[FormView]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
@@ -200,7 +205,7 @@ func AdminSettingsSchema() {}
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param code path string true "Settings code"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[SettingsResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
@@ -215,10 +220,11 @@ func AdminSettingsGet() {}
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param code path string true "Settings code"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[SettingsResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /settings/{code} [put]
|
||||
func AdminSettingsPut() {}
|
||||
|
||||
@@ -293,6 +299,24 @@ func AdminRelationSchema() {}
|
||||
// @Router /{vendor}/{plugin}/{controller}/fields/{field}/options [get]
|
||||
func AdminFieldOptions() {}
|
||||
|
||||
// AdminFilterOptions documents the model-backed filter options route (D-27).
|
||||
//
|
||||
// @Summary Filter scope options
|
||||
// @Description Choices of a declared scope filter of the controller's list, from the model's FilterOptions. {scope} is the filter name used as filter[<scope>]; labels are localized.
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security BackendBearer
|
||||
// @Param vendor path string true "Vendor"
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param scope path string true "Filter name"
|
||||
// @Success 200 {object} Envelope[[]FilterOption]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/filters/{scope}/options [get]
|
||||
func AdminFilterOptions() {}
|
||||
|
||||
// AdminList documents the record list route.
|
||||
//
|
||||
// @Summary List admin records
|
||||
@@ -311,6 +335,7 @@ func AdminFieldOptions() {}
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller} [get]
|
||||
func AdminList() {}
|
||||
|
||||
@@ -329,6 +354,7 @@ func AdminList() {}
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller} [post]
|
||||
func AdminCreate() {}
|
||||
|
||||
@@ -342,10 +368,12 @@ func AdminCreate() {}
|
||||
// @Param vendor path string true "Vendor"
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[BulkResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 409 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/bulk-delete [post]
|
||||
func AdminBulkDelete() {}
|
||||
|
||||
@@ -395,10 +423,11 @@ func AdminUpdate() {}
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Record id"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[BulkResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id} [delete]
|
||||
func AdminDelete() {}
|
||||
|
||||
@@ -413,9 +442,11 @@ func AdminDelete() {}
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} ListEnvelope[[]AdminRecord]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name} [get]
|
||||
func AdminRelationLinked() {}
|
||||
|
||||
@@ -430,9 +461,11 @@ func AdminRelationLinked() {}
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} ListEnvelope[[]AdminRecord]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/candidates [get]
|
||||
func AdminRelationCandidates() {}
|
||||
|
||||
@@ -448,10 +481,11 @@ func AdminRelationCandidates() {}
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[RelationMutationResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/link [post]
|
||||
func AdminRelationLink() {}
|
||||
|
||||
@@ -467,9 +501,10 @@ func AdminRelationLink() {}
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param id path integer true "Owner id"
|
||||
// @Param name path string true "Relation name"
|
||||
// @Success 200 {object} SuccessEnvelope
|
||||
// @Success 200 {object} Envelope[RelationMutationResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
// @Failure 422 {object} ErrorEnvelope
|
||||
// @Failure 404 {object} ErrorEnvelope
|
||||
// @Router /{vendor}/{plugin}/{controller}/{id}/relations/{name}/unlink [post]
|
||||
func AdminRelationUnlink() {}
|
||||
|
||||
Reference in New Issue
Block a user