feat(all): split client tooling and add OAuth server login

This commit is contained in:
2026-09-30 17:32:14 +08:00
parent 7cb5e36c2a
commit 50e2572385
230 changed files with 9875 additions and 853 deletions
+45
View File
@@ -0,0 +1,45 @@
package stateio
import (
"encoding/json"
"fmt"
"sort"
"strings"
)
// RequireExactJSONObject makes the persisted layout part of the current
// storage contract. It rejects both missing and unknown fields rather than
// allowing encoding/json to silently interpret an older or newer format.
func RequireExactJSONObject(payload []byte, required ...string) error {
var fields map[string]json.RawMessage
if err := json.Unmarshal(payload, &fields); err != nil {
return err
}
if fields == nil {
return fmt.Errorf("state payload is not an object")
}
want := make(map[string]bool, len(required))
for _, name := range required {
if name == "" || want[name] {
return fmt.Errorf("invalid required field %q", name)
}
want[name] = true
}
var missing, unknown []string
for name := range want {
if _, exists := fields[name]; !exists {
missing = append(missing, name)
}
}
for name := range fields {
if !want[name] {
unknown = append(unknown, name)
}
}
if len(missing) == 0 && len(unknown) == 0 {
return nil
}
sort.Strings(missing)
sort.Strings(unknown)
return fmt.Errorf("state fields mismatch: missing=[%s] unknown=[%s]", strings.Join(missing, ","), strings.Join(unknown, ","))
}