Compare commits

..

4 Commits

Author SHA1 Message Date
Alex Dunmow
62c25a7b3a feat: add settings.Updater interface to ServiceDeps 2026-05-02 11:03:40 +08:00
Alex Dunmow
2c89ce4d42 feat: add BadgeRefresher interface and badge types 2026-05-02 11:03:09 +08:00
Alex Dunmow
1ede7d50be feat: add ReviewSubmitter interface to ServiceDeps 2026-05-02 11:02:28 +08:00
Alex Dunmow
a174eb943d feat: add CoreServiceBindings interface to ServiceDeps 2026-05-02 11:02:08 +08:00
5 changed files with 96 additions and 0 deletions

42
badges/badges.go Normal file
View File

@ -0,0 +1,42 @@
package badges
import "encoding/json"
// BadgeRule defines a condition for automatic badge assignment.
type BadgeRule struct {
Field string `json:"field"`
Operator string `json:"operator"` // eq, neq, gt, gte, lt, lte, contains, exists, true, false
Value any `json:"value"`
}
// BadgeDefinition defines a badge with auto-computation rules.
type BadgeDefinition struct {
Key string `json:"key"`
Label string `json:"label"`
Description string `json:"description"`
Icon string `json:"icon"`
Rules []BadgeRule `json:"rules"`
RulesMode string `json:"rules_mode"` // "and" or "or"
ManualOnly bool `json:"manual_only"`
}
// ParseDefinitions extracts badge definitions from a data table schema JSON.
func ParseDefinitions(schemaJSON []byte) []BadgeDefinition {
var schema map[string]any
if err := json.Unmarshal(schemaJSON, &schema); err != nil {
return nil
}
badgesRaw, ok := schema["badges"]
if !ok {
return nil
}
raw, err := json.Marshal(badgesRaw)
if err != nil {
return nil
}
var definitions []BadgeDefinition
if err := json.Unmarshal(raw, &definitions); err != nil {
return nil
}
return definitions
}

13
plugin/community.go Normal file
View File

@ -0,0 +1,13 @@
package plugin
import (
"git.dev.alexdunmow.com/block/core/rbac"
)
// CoreServiceBindings provides pre-built CMS service bindings that plugins
// can include in their ServiceRegistration with custom RBAC role mappings.
// The CMS constructs the actual service handlers — plugins just specify which
// services to mount and what roles apply.
type CoreServiceBindings interface {
Bind(serviceName string, methodRoles map[string]rbac.Role) (ConnectServiceBinding, error)
}

View File

@ -46,6 +46,12 @@ type ServiceDeps struct {
// Plugin interop
Bridge PluginBridge
// Core RPC services — pre-built bindings for CMS-provided services
CoreServiceBindings CoreServiceBindings
ReviewSubmitter ReviewSubmitter
BadgeRefresher BadgeRefresher
SettingsUpdater settings.Updater
// Extension points — typed as narrow interfaces where possible
JobRunner JobRunner
EmbeddingService EmbeddingService
@ -81,3 +87,10 @@ type RAGResult struct {
Score float64
Metadata map[string]string
}
// BadgeRefresher recomputes badges for a data table row.
// The CMS handles loading the table schema, aggregating ratings,
// evaluating badge rules, and persisting the updated badge list.
type BadgeRefresher interface {
RefreshBadges(ctx context.Context, tableID, rowID uuid.UUID) error
}

23
plugin/reviews.go Normal file
View File

@ -0,0 +1,23 @@
package plugin
import (
"context"
"github.com/google/uuid"
)
// ReviewSubmitter allows plugins to submit community reviews programmatically
// without importing CMS proto types.
type ReviewSubmitter interface {
SubmitReview(ctx context.Context, params SubmitReviewParams) (reviewID string, err error)
}
// SubmitReviewParams contains the fields needed to submit a community review.
type SubmitReviewParams struct {
TableID uuid.UUID
RowID uuid.UUID
OverallRating int32
ReviewText string
Ratings map[string]any
Photos []string
}

View File

@ -8,6 +8,11 @@ type Settings interface {
GetPluginSettings(ctx context.Context, pluginName string) (map[string]any, error)
}
// Updater allows plugins to modify site settings.
type Updater interface {
UpdateSiteSetting(ctx context.Context, key string, value any) error
}
// GetStringOr returns a string value from a map, or defaultVal if not found/wrong type.
func GetStringOr(m map[string]any, key, defaultVal string) string {
if v, ok := m[key].(string); ok {