diff --git a/apps/moltnet-cli/README.md b/apps/moltnet-cli/README.md index f9e006899..c5163817a 100644 --- a/apps/moltnet-cli/README.md +++ b/apps/moltnet-cli/README.md @@ -75,6 +75,7 @@ moltnet vouch list # List your active (unredeemed) vouchers ```bash moltnet config repair # Validate and fix moltnet.json +moltnet config schema # Print JSON Schema for moltnet.json moltnet ssh-key # Export identity as SSH key files moltnet git setup # Configure git for SSH commit signing moltnet github setup # Configure git for GitHub App identity @@ -90,6 +91,9 @@ moltnet help ## Configuration Credentials are stored at `~/.config/moltnet/moltnet.json` after `moltnet register`. +Generated config files include a `$schema` pointer to +`https://api.themolt.net/schemas/moltnet-config/v1.json` for IDE validation and +autocomplete. All API commands accept `--api-url` to override the default (`https://api.themolt.net`). diff --git a/apps/moltnet-cli/cobra_cli_test.go b/apps/moltnet-cli/cobra_cli_test.go index 89b9353e1..91f6038f2 100644 --- a/apps/moltnet-cli/cobra_cli_test.go +++ b/apps/moltnet-cli/cobra_cli_test.go @@ -1137,6 +1137,18 @@ func TestEntryCommitAcceptsWriter(t *testing.T) { // --- Issue 3+4: --credentials flag is plumbed through --- +func TestConfigSchemaCommand(t *testing.T) { + t.Parallel() + root := NewRootCmd("test", "") + stdout, _, err := executeCommand(root, "config", "schema") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if stdout != string(embeddedMoltnetConfigSchema) { + t.Fatal("config schema output mismatch") + } +} + func TestCredentialsFlagPlumbedToAgentsWhoami(t *testing.T) { // Create a valid credentials file with OAuth2 creds pointing at unreachable API kp, err := GenerateKeyPair() diff --git a/apps/moltnet-cli/cobra_config.go b/apps/moltnet-cli/cobra_config.go index 8792fc7bb..df9dc8750 100644 --- a/apps/moltnet-cli/cobra_config.go +++ b/apps/moltnet-cli/cobra_config.go @@ -1,6 +1,8 @@ package main -import "github.com/spf13/cobra" +import ( + "github.com/spf13/cobra" +) func newConfigCmd() *cobra.Command { configCmd := &cobra.Command{ @@ -65,6 +67,16 @@ Optional env vars: initFromEnvCmd.Flags().String("env-file", "", "Load variables from a dotenv file") initFromEnvCmd.Flags().Bool("override", false, "Let env-file values override process environment") + schemaCmd := &cobra.Command{ + Use: "schema", + Short: "Print the JSON Schema for moltnet.json", + Example: ` moltnet config schema + moltnet config schema > moltnet-config.schema.json`, + RunE: func(cmd *cobra.Command, args []string) error { + return runConfigSchemaCmd(cmd.OutOrStdout()) + }, + } + exportEnvCmd := &cobra.Command{ Use: "export-env", Short: "Export agent config as MOLTNET_* environment variables", @@ -90,6 +102,7 @@ usable with init-from-env --env-file.`, exportEnvCmd.Flags().Bool("include-github-pem", false, "Include GitHub App private key content") configCmd.AddCommand(repairCmd) + configCmd.AddCommand(schemaCmd) configCmd.AddCommand(initFromEnvCmd) configCmd.AddCommand(exportEnvCmd) return configCmd diff --git a/apps/moltnet-cli/credentials.go b/apps/moltnet-cli/credentials.go index 422b2402a..f12df2769 100644 --- a/apps/moltnet-cli/credentials.go +++ b/apps/moltnet-cli/credentials.go @@ -9,6 +9,7 @@ import ( // CredentialsFile matches the JS SDK MoltNetConfig format. type CredentialsFile struct { + Schema string `json:"$schema,omitempty" jsonschema:"format=uri"` IdentityID string `json:"identity_id"` OAuth2 CredentialsOAuth2 `json:"oauth2"` Keys CredentialsKeys `json:"keys"` @@ -137,7 +138,12 @@ func WriteConfigTo(config *CredentialsFile, path string) (string, error) { return "", fmt.Errorf("create config dir: %w", err) } - data, err := json.MarshalIndent(config, "", " ") + configWithSchema := *config + if configWithSchema.Schema == "" { + configWithSchema.Schema = moltnetConfigSchemaURL + } + + data, err := json.MarshalIndent(&configWithSchema, "", " ") if err != nil { return "", fmt.Errorf("marshal config: %w", err) } diff --git a/apps/moltnet-cli/credentials_test.go b/apps/moltnet-cli/credentials_test.go index 6d7d9d2b8..9291485ff 100644 --- a/apps/moltnet-cli/credentials_test.go +++ b/apps/moltnet-cli/credentials_test.go @@ -151,6 +151,9 @@ func TestWriteConfig(t *testing.T) { if read.IdentityID != "uuid-write-test" { t.Errorf("identity_id: got %s", read.IdentityID) } + if read.Schema != moltnetConfigSchemaURL { + t.Errorf("$schema: got %s, want %s", read.Schema, moltnetConfigSchemaURL) + } } func TestOptionalSections(t *testing.T) { @@ -243,6 +246,9 @@ func TestOptionalSections_OmitEmpty(t *testing.T) { var raw map[string]interface{} json.Unmarshal(data, &raw) + if raw["$schema"] != moltnetConfigSchemaURL { + t.Errorf("$schema: got %v, want %s", raw["$schema"], moltnetConfigSchemaURL) + } if _, exists := raw["ssh"]; exists { t.Error("ssh should be omitted when nil") } diff --git a/apps/moltnet-cli/go.mod b/apps/moltnet-cli/go.mod index 8cf1bb2dc..68e9d0ed0 100644 --- a/apps/moltnet-cli/go.mod +++ b/apps/moltnet-cli/go.mod @@ -8,6 +8,7 @@ require ( github.com/getlarge/themoltnet/libs/moltnet-api-client v1.28.0 github.com/go-faster/jx v1.2.0 github.com/google/uuid v1.6.0 + github.com/invopop/jsonschema v0.13.0 github.com/ipfs/go-cid v0.6.0 github.com/joho/godotenv v1.5.1 github.com/multiformats/go-multihash v0.2.3 @@ -24,6 +25,8 @@ require ( github.com/XiaoConstantine/mcp-go v0.3.1 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/anthropics/anthropic-sdk-go v1.27.1 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/buger/jsonparser v1.1.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/dlclark/regexp2 v1.11.5 // indirect @@ -40,6 +43,7 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.20 // indirect @@ -57,6 +61,7 @@ require ( github.com/tidwall/match v1.2.0 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/otel v1.40.0 // indirect go.opentelemetry.io/otel/metric v1.40.0 // indirect diff --git a/apps/moltnet-cli/go.sum b/apps/moltnet-cli/go.sum index 6621bab39..dc2f9cdf5 100644 --- a/apps/moltnet-cli/go.sum +++ b/apps/moltnet-cli/go.sum @@ -16,6 +16,10 @@ github.com/apache/arrow/go/v13 v13.0.0 h1:kELrvDQuKZo8csdWYqBQfyi431x6Zs/YJTEgUu github.com/apache/arrow/go/v13 v13.0.0/go.mod h1:W69eByFNO0ZR30q1/7Sr9d83zcVZmF2MiP3fFYAWJOc= github.com/apache/thrift v0.22.0 h1:r7mTJdj51TMDe6RtcmNdQxgn9XcyfGDOzegMDRg47uc= github.com/apache/thrift v0.22.0/go.mod h1:1e7J/O1Ae6ZQMTYdy9xa3w9k+XHWPfRvdPyJeynQ+/g= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= @@ -68,10 +72,13 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= +github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/ipfs/go-cid v0.6.0 h1:DlOReBV1xhHBhhfy/gBNNTSyfOM6rLiIx9J7A4DGf30= github.com/ipfs/go-cid v0.6.0/go.mod h1:NC4kS1LZjzfhK40UGmpXv5/qD2kcMzACYJNntCUiDhQ= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= @@ -86,6 +93,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -147,6 +156,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/vbauerster/mpb/v8 v8.12.0 h1:+gneY3ifzc88tKDzOtfG8k8gfngCx615S2ZmFM4liWg= github.com/vbauerster/mpb/v8 v8.12.0/go.mod h1:V02YIuMVo301Y1VE9VtZlD8s84OMsk+EKN6mwvf/588= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= diff --git a/apps/moltnet-cli/repair.go b/apps/moltnet-cli/repair.go index c8b4ed2eb..2cbabacaa 100644 --- a/apps/moltnet-cli/repair.go +++ b/apps/moltnet-cli/repair.go @@ -118,6 +118,14 @@ func loadAndValidate(credPath string) (string, *CredentialsFile, []ConfigIssue, } } + if creds.Schema == "" { + creds.Schema = moltnetConfigSchemaURL + issues = append(issues, ConfigIssue{Field: "$schema", Problem: "missing — set to canonical MoltNet config schema", Action: "fixed"}) + } else if creds.Schema != moltnetConfigSchemaURL { + creds.Schema = moltnetConfigSchemaURL + issues = append(issues, ConfigIssue{Field: "$schema", Problem: "incorrect — updated to " + moltnetConfigSchemaURL, Action: "fixed"}) + } + // Required fields if creds.IdentityID == "" { issues = append(issues, ConfigIssue{Field: "identity_id", Problem: "missing", Action: "warning"}) diff --git a/apps/moltnet-cli/repair_test.go b/apps/moltnet-cli/repair_test.go index 42e644ea6..ac71d6ca7 100644 --- a/apps/moltnet-cli/repair_test.go +++ b/apps/moltnet-cli/repair_test.go @@ -12,6 +12,7 @@ func TestLoadAndValidate_ValidConfig(t *testing.T) { tmpDir := t.TempDir() creds := CredentialsFile{ + Schema: moltnetConfigSchemaURL, IdentityID: "test-agent-12345678", Keys: CredentialsKeys{ PublicKey: "ed25519:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik=", @@ -79,17 +80,27 @@ func TestLoadAndValidate_FixesMissingMCP(t *testing.T) { } var fixedMCP bool + var fixedSchema bool for _, iss := range issues { if iss.Field == "endpoints.mcp" && iss.Action == "fixed" { fixedMCP = true } + if iss.Field == "$schema" && iss.Action == "fixed" { + fixedSchema = true + } } if !fixedMCP { t.Error("expected 'fixed' issue for endpoints.mcp") } + if !fixedSchema { + t.Error("expected 'fixed' issue for $schema") + } if updated.Endpoints.MCP != "https://mcp.themolt.net/mcp" { t.Errorf("MCP endpoint = %q, want %q", updated.Endpoints.MCP, "https://mcp.themolt.net/mcp") } + if updated.Schema != moltnetConfigSchemaURL { + t.Errorf("$schema = %q, want %q", updated.Schema, moltnetConfigSchemaURL) + } } func TestLoadAndValidate_StaleSSHPaths(t *testing.T) { @@ -227,6 +238,9 @@ func TestRunConfigRepair_AppliesFixes(t *testing.T) { if updated.Endpoints.MCP != "https://mcp.themolt.net/mcp" { t.Errorf("MCP endpoint = %q, want %q", updated.Endpoints.MCP, "https://mcp.themolt.net/mcp") } + if updated.Schema != moltnetConfigSchemaURL { + t.Errorf("$schema = %q, want %q", updated.Schema, moltnetConfigSchemaURL) + } } func TestLoadAndValidate_EnvAuthorshipInvalid(t *testing.T) { diff --git a/apps/moltnet-cli/schema.go b/apps/moltnet-cli/schema.go new file mode 100644 index 000000000..195545d0d --- /dev/null +++ b/apps/moltnet-cli/schema.go @@ -0,0 +1,37 @@ +package main + +import ( + _ "embed" + "encoding/json" + "fmt" + "io" + + "github.com/invopop/jsonschema" +) + +const moltnetConfigSchemaURL = "https://api.themolt.net/schemas/moltnet-config/v1.json" +const jsonSchemaDraft2020_12 = "https://json-schema.org/draft/2020-12/schema" + +//go:embed schema/moltnet-config.v1.json +var embeddedMoltnetConfigSchema []byte + +func runConfigSchemaCmd(w io.Writer) error { + _, err := w.Write(embeddedMoltnetConfigSchema) + return err +} + +func marshalMoltnetConfigSchema() ([]byte, error) { + reflector := &jsonschema.Reflector{DoNotReference: true} + schema := reflector.Reflect(&CredentialsFile{}) + schema.Version = jsonSchemaDraft2020_12 + schema.ID = jsonschema.ID(moltnetConfigSchemaURL) + schema.Title = "MoltNet credentials file" + schema.Description = "JSON Schema for moltnet.json agent credentials." + + data, err := json.MarshalIndent(schema, "", " ") + if err != nil { + return nil, fmt.Errorf("marshal schema: %w", err) + } + + return append(data, '\n'), nil +} diff --git a/apps/moltnet-cli/schema/moltnet-config.v1.json b/apps/moltnet-cli/schema/moltnet-config.v1.json new file mode 100644 index 000000000..d26d2c60d --- /dev/null +++ b/apps/moltnet-cli/schema/moltnet-config.v1.json @@ -0,0 +1,117 @@ +{ + "$id": "https://api.themolt.net/schemas/moltnet-config/v1.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "JSON Schema for moltnet.json agent credentials.", + "properties": { + "$schema": { + "format": "uri", + "type": "string" + }, + "endpoints": { + "additionalProperties": false, + "properties": { + "api": { + "type": "string" + }, + "mcp": { + "type": "string" + } + }, + "required": ["api", "mcp"], + "type": "object" + }, + "git": { + "additionalProperties": false, + "properties": { + "config_path": { + "type": "string" + }, + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "signing": { + "type": "boolean" + } + }, + "required": ["name", "email", "signing", "config_path"], + "type": "object" + }, + "github": { + "additionalProperties": false, + "properties": { + "app_id": { + "type": "string" + }, + "app_slug": { + "type": "string" + }, + "installation_id": { + "type": "string" + }, + "org": { + "type": "string" + }, + "private_key_path": { + "type": "string" + } + }, + "required": ["app_id", "installation_id", "private_key_path"], + "type": "object" + }, + "identity_id": { + "type": "string" + }, + "keys": { + "additionalProperties": false, + "properties": { + "fingerprint": { + "type": "string" + }, + "private_key": { + "type": "string" + }, + "public_key": { + "type": "string" + } + }, + "required": ["public_key", "private_key", "fingerprint"], + "type": "object" + }, + "oauth2": { + "additionalProperties": false, + "properties": { + "client_id": { + "type": "string" + }, + "client_secret": { + "type": "string" + } + }, + "required": ["client_id", "client_secret"], + "type": "object" + }, + "registered_at": { + "type": "string" + }, + "ssh": { + "additionalProperties": false, + "properties": { + "private_key_path": { + "type": "string" + }, + "public_key_path": { + "type": "string" + } + }, + "required": ["private_key_path", "public_key_path"], + "type": "object" + } + }, + "required": ["identity_id", "oauth2", "keys", "endpoints", "registered_at"], + "title": "MoltNet credentials file", + "type": "object" +} diff --git a/apps/moltnet-cli/schema_test.go b/apps/moltnet-cli/schema_test.go new file mode 100644 index 000000000..402756e58 --- /dev/null +++ b/apps/moltnet-cli/schema_test.go @@ -0,0 +1,52 @@ +package main + +import ( + "encoding/json" + "reflect" + "testing" +) + +func TestMarshalMoltnetConfigSchema_MatchesEmbedded(t *testing.T) { + generated, err := marshalMoltnetConfigSchema() + if err != nil { + t.Fatalf("marshalMoltnetConfigSchema: %v", err) + } + + var generatedSchema map[string]any + if err := json.Unmarshal(generated, &generatedSchema); err != nil { + t.Fatalf("json.Unmarshal(generated): %v", err) + } + + var embeddedSchema map[string]any + if err := json.Unmarshal(embeddedMoltnetConfigSchema, &embeddedSchema); err != nil { + t.Fatalf("json.Unmarshal(embedded): %v", err) + } + + if !reflect.DeepEqual(generatedSchema, embeddedSchema) { + t.Fatalf("embedded schema is out of date; regenerate apps/moltnet-cli/schema/moltnet-config.v1.json") + } +} + +func TestMarshalMoltnetConfigSchema_IncludesSchemaField(t *testing.T) { + generated, err := marshalMoltnetConfigSchema() + if err != nil { + t.Fatalf("marshalMoltnetConfigSchema: %v", err) + } + + var schema map[string]any + if err := json.Unmarshal(generated, &schema); err != nil { + t.Fatalf("json.Unmarshal: %v", err) + } + + if schema["$id"] != moltnetConfigSchemaURL { + t.Fatalf("$id = %v, want %q", schema["$id"], moltnetConfigSchemaURL) + } + + properties, ok := schema["properties"].(map[string]any) + if !ok { + t.Fatal("schema.properties missing or invalid") + } + if _, ok := properties["$schema"]; !ok { + t.Fatal("schema missing $schema property") + } +} diff --git a/go.work.sum b/go.work.sum index ed6c564cc..6bcc9c438 100644 --- a/go.work.sum +++ b/go.work.sum @@ -15,7 +15,9 @@ github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeI github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw= github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ= github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/getlarge/themoltnet/libs/moltnet-api-client v1.27.0/go.mod h1:2NM6Nj6POFphfql+G6u6/4F2i3EIo5Jd95DBX1lhPLM= @@ -23,13 +25,16 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-sqlite3 v1.14.37/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/traefik/yaegi v0.16.1/go.mod h1:4eVhbPb3LnD2VigQjhYbEJ69vDRFdT2HQNrXx8eEwUY= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.69.0/go.mod h1:4wA4PfAraPlAsJ5jMSqCE2ug5tqUPwKXxVj8oNECGcw= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=