feat(owner): 扫码绑定确认时自动把主人id登记进owner.yaml白名单(热生效)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

This commit is contained in:
Aska committed 2026-09-08 02:53:01 +08:00
1 parent 0aa387f83c
commit 5a7ee9d772
7 files changed
+487 -65

No files matched your search

+48 -27
View File
@@ -176,6 +176,18 @@ type ChannelConfigStore interface {
Reload(platform string) error
}
// OwnerRegistrar registers a channel account id into the owner whitelist
// (configs/users/owner.yaml). It is the structural identity red line: a scan-login
// confirmation stamps the scanner's bound ilink_user_id into the whitelist so the
// channel bridge recognizes it as the owner via actor metadata, never a prompt.
// The composition root implements it (cmd/cyrene's ownerRegistrar) to persist the
// whitelist and hot-update the live owner profile. Registration is best-effort:
// a failure is logged by the caller but does not fail the already-applied
// channels.json persist.
type OwnerRegistrar interface {
RegisterChannelOwner(ctx context.Context, platform, accountID string) error
}
// RagStore backs the admin knowledge-base RAG module (design/10 §3.12 module 8).
// *runtime/knowledge.Store is the production implementation. Every method is
// read-only for this milestone: IndexDocument/DeleteDocument return a clear
@@ -245,6 +257,11 @@ type Deps struct {
// Optional: when nil the admin /channels/config endpoints return a clear
// not-configured error, matching how the LLM stack behaves when unset.
Channels ChannelConfigStore
// OwnerRegistrar stamps a scan-login's bound owner id into the owner
// whitelist (configs/users/owner.yaml) and hot-updates the live profile.
// Optional: when nil the weixin confirm flow still persists channels.json but
// skips the whitelist registration (best-effort by design).
OwnerRegistrar OwnerRegistrar
// AuditStore persists the admin audit trail (observability → audit). When nil
// the gateway degrades to an in-memory store so the endpoint still returns
// data; the composition root injects NewSQLiteAuditStore over a.db for real
@@ -301,9 +318,12 @@ type Server struct {
// that do not wire it keep working.
llm *model.RuntimeLLM
channels ChannelConfigStore
webhooks map[string]http.Handler
log *slog.Logger
hub *hub
// ownerRegistrar stamps a scan-login bound owner id into the owner whitelist
// (best-effort). See Deps.OwnerRegistrar.
ownerRegistrar OwnerRegistrar
webhooks map[string]http.Handler
log *slog.Logger
hub *hub
}
// New validates cfg and deps and returns a ready Server. Auth is required; the
@@ -317,30 +337,31 @@ func New(cfg *config.Config, deps Deps) (*Server, error) {
return nil, fmt.Errorf("gateway: auth dependency required")
}
s := &Server{
cfg: cfg,
auth: deps.Auth,
bus: deps.Bus,
caps: deps.Registry,
runner: deps.Loop,
sessions: deps.Session,
personas: deps.Personas,
memories: deps.Memories,
history: deps.History,
iot: deps.IoT,
auditor: deps.Scheduler,
taskOutputs: deps.Tasks,
automations: deps.Automations,
users: deps.Users,
backthink: deps.Backthink,
rag: deps.RAG,
obs: newObservability(deps),
streaming: deps.Streaming,
frontend: deps.Frontend,
llm: deps.LLM,
channels: deps.Channels,
webhooks: deps.Webhooks,
dbPath: deps.DatabasePath,
log: sourcedLog(deps.Log),
cfg: cfg,
auth: deps.Auth,
bus: deps.Bus,
caps: deps.Registry,
runner: deps.Loop,
sessions: deps.Session,
personas: deps.Personas,
memories: deps.Memories,
history: deps.History,
iot: deps.IoT,
auditor: deps.Scheduler,
taskOutputs: deps.Tasks,
automations: deps.Automations,
users: deps.Users,
backthink: deps.Backthink,
rag: deps.RAG,
obs: newObservability(deps),
streaming: deps.Streaming,
frontend: deps.Frontend,
llm: deps.LLM,
channels: deps.Channels,
ownerRegistrar: deps.OwnerRegistrar,
webhooks: deps.Webhooks,
dbPath: deps.DatabasePath,
log: sourcedLog(deps.Log),
}
s.hub = newHub(s)
s.hub.orchestrator = newOrchestrator(s)