Opening a shop is an API call; the broker learns of it in the same request
The last step of onboarding that needed a shell: provision site printed a broker password and a person typed it into Mosquitto's passwd file on the host - mounted read-only in the container, so the first attempt failed silently and the password was re-rolled. No tenant could open a second branch without us. The server now drives Mosquitto's dynamic-security plugin over its own broker login: POST /api/sites (owner) writes the row and the sealed password, registers the login and a per-site role with literal topics (the 2.0 plugin does not substitute %u - measured), and removes the row again if the broker refuses, so a shop cannot exist in the database and not on the broker. provision site goes through the same path. The head-office Shops screen gets 'Open a new shop'. broker-init converts the existing passwd file into the plugin's store with every hash intact - PBKDF2-SHA512 both sides - so the cutover re-claims no shop PC. Rehearsed locally: old logins keep working, isolation holds, the health probe works, and a PC claiming a shop opened through the API connects as that shop. run-local.sh now brings the broker up the same way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
This commit is contained in:
@@ -25,11 +25,12 @@ import (
|
||||
"github.com/loyaly/behavision-server/internal/api"
|
||||
"github.com/loyaly/behavision-server/internal/assistant"
|
||||
"github.com/loyaly/behavision-server/internal/blob"
|
||||
"github.com/loyaly/behavision-server/internal/broker"
|
||||
"github.com/loyaly/behavision-server/internal/ingest"
|
||||
"github.com/loyaly/behavision-server/internal/migrate"
|
||||
"github.com/loyaly/behavision-server/internal/web"
|
||||
"github.com/loyaly/behavision-server/internal/secret"
|
||||
"github.com/loyaly/behavision-server/internal/store"
|
||||
"github.com/loyaly/behavision-server/internal/web"
|
||||
"github.com/loyaly/behavision-server/migrations"
|
||||
)
|
||||
|
||||
@@ -46,6 +47,13 @@ func main() {
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(os.Args) > 1 && os.Args[1] == "broker-init" {
|
||||
if err := runBrokerInit(os.Args[2:]); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(os.Args) > 1 && os.Args[1] == "migrate" {
|
||||
if err := runMigrate(os.Args[2:]); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
@@ -194,8 +202,11 @@ func run() error {
|
||||
apiSrv := &api.Server{
|
||||
Store: st,
|
||||
Log: logger,
|
||||
Blob: objectStore(ctx, logger),
|
||||
Hub: hub,
|
||||
// Opening a shop registers its broker login at the same moment, over the
|
||||
// same broker credential the ingest side already holds.
|
||||
Broker: broker.New(brokerURL, brokerUser, brokerPass, logger),
|
||||
Blob: objectStore(ctx, logger),
|
||||
Hub: hub,
|
||||
Bootstrap: api.BootstrapConfig{
|
||||
// What an enrolling PC is told to connect to. From the server's own
|
||||
// environment, never from the request: an agent asking where to
|
||||
|
||||
Reference in New Issue
Block a user