diff --git a/cmd/validate-lexicon/main.go b/cmd/validate-lexicon/main.go index ab93d46..3b8fffa 100644 --- a/cmd/validate-lexicon/main.go +++ b/cmd/validate-lexicon/main.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "encoding/json" "flag" "fmt" @@ -270,12 +271,17 @@ func validateTestData(catalog *lexicon.BaseCatalog, testDataPath string, verbose return nil } - // Parse JSON data + // Parse JSON data using Decoder to handle numbers properly var recordData map[string]interface{} - if err := json.Unmarshal(data, &recordData); err != nil { + decoder := json.NewDecoder(bytes.NewReader(data)) + decoder.UseNumber() // This preserves numbers as json.Number instead of float64 + if err := decoder.Decode(&recordData); err != nil { validationErrors = append(validationErrors, fmt.Sprintf("Failed to parse JSON in %s: %v", path, err)) return nil } + + // Convert json.Number values to appropriate types + recordData = convertNumbers(recordData).(map[string]interface{}) // Extract $type field recordType, ok := recordData["$type"].(string) @@ -438,3 +444,34 @@ func validateCrossReferences(catalog *lexicon.BaseCatalog, verbose bool) error { return nil } + +// convertNumbers recursively converts json.Number values to int64 or float64 +func convertNumbers(v interface{}) interface{} { + switch vv := v.(type) { + case map[string]interface{}: + result := make(map[string]interface{}) + for k, val := range vv { + result[k] = convertNumbers(val) + } + return result + case []interface{}: + result := make([]interface{}, len(vv)) + for i, val := range vv { + result[i] = convertNumbers(val) + } + return result + case json.Number: + // Try to convert to int64 first + if i, err := vv.Int64(); err == nil { + return i + } + // If that fails, convert to float64 + if f, err := vv.Float64(); err == nil { + return f + } + // If both fail, return as string + return vv.String() + default: + return v + } +} diff --git a/internal/atproto/lexicon/social/coves/actor/profile.json b/internal/atproto/lexicon/social/coves/actor/profile.json index b13fcca..90da1ca 100644 --- a/internal/atproto/lexicon/social/coves/actor/profile.json +++ b/internal/atproto/lexicon/social/coves/actor/profile.json @@ -12,6 +12,7 @@ "properties": { "handle": { "type": "string", + "format": "handle", "maxLength": 253, "description": "User's handle" }, diff --git a/internal/atproto/lexicon/social/coves/community/profile.json b/internal/atproto/lexicon/social/coves/community/profile.json index 8d9e75c..84123ce 100644 --- a/internal/atproto/lexicon/social/coves/community/profile.json +++ b/internal/atproto/lexicon/social/coves/community/profile.json @@ -52,7 +52,7 @@ }, "moderationType": { "type": "string", - "knownValues": ["moderator", "sortition"], + "enum": ["moderator", "sortition"], "description": "Type of moderation system" }, "contentWarnings": { diff --git a/internal/atproto/lexicon/social/coves/interaction/comment.json b/internal/atproto/lexicon/social/coves/interaction/comment.json index 915937f..12482ef 100644 --- a/internal/atproto/lexicon/social/coves/interaction/comment.json +++ b/internal/atproto/lexicon/social/coves/interaction/comment.json @@ -60,7 +60,7 @@ "properties": { "image": { "type": "ref", - "ref": "social.coves.embed.image" + "ref": "social.coves.embed.images#image" }, "caption": { "type": "string", diff --git a/internal/atproto/lexicon/social/coves/interaction/tag.json b/internal/atproto/lexicon/social/coves/interaction/tag.json index dd0632f..bcc616b 100644 --- a/internal/atproto/lexicon/social/coves/interaction/tag.json +++ b/internal/atproto/lexicon/social/coves/interaction/tag.json @@ -17,6 +17,8 @@ }, "tag": { "type": "string", + "minLength": 1, + "maxLength": 50, "knownValues": ["helpful", "insightful", "spam", "hostile", "offtopic", "misleading"], "description": "Predefined tag or custom community tag" }, diff --git a/internal/atproto/lexicon/social/coves/moderation/ruleProposal.json b/internal/atproto/lexicon/social/coves/moderation/ruleProposal.json index 768a989..cd8be1b 100644 --- a/internal/atproto/lexicon/social/coves/moderation/ruleProposal.json +++ b/internal/atproto/lexicon/social/coves/moderation/ruleProposal.json @@ -17,7 +17,7 @@ }, "proposalType": { "type": "string", - "knownValues": [ + "enum": [ "addTag", "removeTag", "blockDomain", @@ -60,7 +60,7 @@ }, "status": { "type": "string", - "knownValues": ["active", "passed", "failed", "cancelled", "implemented"], + "enum": ["active", "passed", "failed", "cancelled", "implemented"], "default": "active" }, "votingStartsAt": { diff --git a/internal/atproto/lexicon/social/coves/moderation/tribunalVote.json b/internal/atproto/lexicon/social/coves/moderation/tribunalVote.json index 1d051dc..6cefe2e 100644 --- a/internal/atproto/lexicon/social/coves/moderation/tribunalVote.json +++ b/internal/atproto/lexicon/social/coves/moderation/tribunalVote.json @@ -22,7 +22,7 @@ }, "decision": { "type": "string", - "knownValues": ["remove", "keep", "warn", "ban", "timeout"], + "enum": ["remove", "keep", "warn", "ban", "timeout"], "description": "Tribunal decision" }, "duration": { diff --git a/internal/atproto/lexicon/social/coves/moderation/vote.json b/internal/atproto/lexicon/social/coves/moderation/vote.json index 79de493..0ea633c 100644 --- a/internal/atproto/lexicon/social/coves/moderation/vote.json +++ b/internal/atproto/lexicon/social/coves/moderation/vote.json @@ -17,7 +17,7 @@ }, "vote": { "type": "string", - "knownValues": ["approve", "reject", "abstain"] + "enum": ["approve", "reject", "abstain"] }, "reason": { "type": "string", diff --git a/tests/lexicon-test-data/actor/block-invalid-did.json b/tests/lexicon-test-data/actor/block-invalid-did.json new file mode 100644 index 0000000..812b065 --- /dev/null +++ b/tests/lexicon-test-data/actor/block-invalid-did.json @@ -0,0 +1,5 @@ +{ + "$type": "social.coves.actor.block", + "subject": "not-a-valid-did", + "createdAt": "2025-01-05T09:15:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/block-valid.json b/tests/lexicon-test-data/actor/block-valid.json new file mode 100644 index 0000000..131517b --- /dev/null +++ b/tests/lexicon-test-data/actor/block-valid.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.actor.block", + "subject": "did:plc:blockeduser123", + "createdAt": "2025-01-05T09:15:00Z", + "reason": "Repeated harassment and spam" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/membership-invalid-reputation.json b/tests/lexicon-test-data/actor/membership-invalid-reputation.json new file mode 100644 index 0000000..c7f7b52 --- /dev/null +++ b/tests/lexicon-test-data/actor/membership-invalid-reputation.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.actor.membership", + "community": "did:plc:examplecommunity123", + "createdAt": "2024-01-15T10:30:00Z", + "reputation": -50 +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/membership-valid.json b/tests/lexicon-test-data/actor/membership-valid.json new file mode 100644 index 0000000..327540c --- /dev/null +++ b/tests/lexicon-test-data/actor/membership-valid.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.actor.membership", + "community": "did:plc:examplecommunity123", + "reputation": 150, + "createdAt": "2024-01-15T10:30:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/preferences-invalid-enum.json b/tests/lexicon-test-data/actor/preferences-invalid-enum.json new file mode 100644 index 0000000..69581c2 --- /dev/null +++ b/tests/lexicon-test-data/actor/preferences-invalid-enum.json @@ -0,0 +1,7 @@ +{ + "$type": "social.coves.actor.preferences", + "feedPreferences": { + "defaultFeed": "invalid-feed-type", + "defaultSort": "hot" + } +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/preferences-valid.json b/tests/lexicon-test-data/actor/preferences-valid.json new file mode 100644 index 0000000..d392c5d --- /dev/null +++ b/tests/lexicon-test-data/actor/preferences-valid.json @@ -0,0 +1,40 @@ +{ + "$type": "social.coves.actor.preferences", + "feedPreferences": { + "defaultFeed": "home", + "defaultSort": "hot", + "showNSFW": false, + "blurNSFW": true, + "autoplayVideos": true, + "infiniteScroll": true + }, + "contentFiltering": { + "blockedTags": ["politics", "spoilers"], + "blockedCommunities": ["did:plc:controversialcommunity"], + "mutedWords": ["spam", "scam"], + "languageFilter": ["en", "es"] + }, + "notificationSettings": { + "postReplies": true, + "commentReplies": true, + "mentions": true, + "upvotes": false, + "newFollowers": true, + "communityInvites": true, + "moderatorNotifications": true + }, + "privacySettings": { + "profileVisibility": "public", + "showSubscriptions": true, + "showSavedPosts": false, + "showVoteHistory": false, + "allowDMs": "followers" + }, + "displayPreferences": { + "theme": "dark", + "compactView": false, + "showAvatars": true, + "showThumbnails": true, + "postsPerPage": 25 + } +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/profile-invalid-handle-format.json b/tests/lexicon-test-data/actor/profile-invalid-handle-format.json new file mode 100644 index 0000000..3e11b95 --- /dev/null +++ b/tests/lexicon-test-data/actor/profile-invalid-handle-format.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.actor.profile", + "handle": "invalid handle with spaces", + "displayName": "Test User", + "createdAt": "2024-01-01T00:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/saved-invalid-type.json b/tests/lexicon-test-data/actor/saved-invalid-type.json new file mode 100644 index 0000000..fc0cca3 --- /dev/null +++ b/tests/lexicon-test-data/actor/saved-invalid-type.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.actor.saved", + "subject": "at://did:plc:exampleuser/social.coves.post.record/3k7a3dmb5bk2c", + "type": "article", + "createdAt": "2025-01-09T14:30:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/saved-valid.json b/tests/lexicon-test-data/actor/saved-valid.json new file mode 100644 index 0000000..f41fabe --- /dev/null +++ b/tests/lexicon-test-data/actor/saved-valid.json @@ -0,0 +1,7 @@ +{ + "$type": "social.coves.actor.saved", + "subject": "at://did:plc:exampleuser/social.coves.post.record/3k7a3dmb5bk2c", + "type": "post", + "createdAt": "2025-01-09T14:30:00Z", + "note": "Great tutorial on Go concurrency patterns" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/subscription-invalid-visibility.json b/tests/lexicon-test-data/actor/subscription-invalid-visibility.json new file mode 100644 index 0000000..02df450 --- /dev/null +++ b/tests/lexicon-test-data/actor/subscription-invalid-visibility.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.actor.subscription", + "community": "did:plc:programmingcommunity", + "createdAt": "2024-06-01T08:00:00Z", + "contentVisibility": 10 +} \ No newline at end of file diff --git a/tests/lexicon-test-data/actor/subscription-valid.json b/tests/lexicon-test-data/actor/subscription-valid.json new file mode 100644 index 0000000..537d57a --- /dev/null +++ b/tests/lexicon-test-data/actor/subscription-valid.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.actor.subscription", + "community": "did:plc:programmingcommunity", + "createdAt": "2024-06-01T08:00:00Z", + "contentVisibility": 3 +} \ No newline at end of file diff --git a/tests/lexicon-test-data/community/moderator-invalid-permissions.json b/tests/lexicon-test-data/community/moderator-invalid-permissions.json new file mode 100644 index 0000000..f540a35 --- /dev/null +++ b/tests/lexicon-test-data/community/moderator-invalid-permissions.json @@ -0,0 +1,9 @@ +{ + "$type": "social.coves.community.moderator", + "user": "did:plc:moderator123", + "community": "did:plc:community123", + "role": "moderator", + "permissions": ["remove_posts", "invalid-permission"], + "createdAt": "2024-06-15T10:00:00Z", + "createdBy": "did:plc:owner123" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/community/moderator-valid.json b/tests/lexicon-test-data/community/moderator-valid.json new file mode 100644 index 0000000..2185635 --- /dev/null +++ b/tests/lexicon-test-data/community/moderator-valid.json @@ -0,0 +1,9 @@ +{ + "$type": "social.coves.community.moderator", + "user": "did:plc:trustedmoderator", + "community": "did:plc:programmingcommunity", + "role": "moderator", + "permissions": ["remove_posts", "remove_comments", "manage_wiki"], + "createdAt": "2024-06-15T10:00:00Z", + "createdBy": "did:plc:communityowner" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/community/profile-invalid-moderation-type.json b/tests/lexicon-test-data/community/profile-invalid-moderation-type.json new file mode 100644 index 0000000..45033de --- /dev/null +++ b/tests/lexicon-test-data/community/profile-invalid-moderation-type.json @@ -0,0 +1,9 @@ +{ + "$type": "social.coves.community.profile", + "name": "testcommunity", + "displayName": "Test Community", + "creator": "did:plc:creator123", + "moderationType": "anarchy", + "federatedFrom": "coves", + "createdAt": "2023-12-01T08:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/community/rules-invalid-sortition.json b/tests/lexicon-test-data/community/rules-invalid-sortition.json new file mode 100644 index 0000000..6a17e8d --- /dev/null +++ b/tests/lexicon-test-data/community/rules-invalid-sortition.json @@ -0,0 +1,8 @@ +{ + "$type": "social.coves.community.rules", + "sortitionConfig": { + "tagThreshold": 5, + "tribunalThreshold": 30, + "jurySize": 9 + } +} \ No newline at end of file diff --git a/tests/lexicon-test-data/community/rules-valid.json b/tests/lexicon-test-data/community/rules-valid.json new file mode 100644 index 0000000..9bbdf9d --- /dev/null +++ b/tests/lexicon-test-data/community/rules-valid.json @@ -0,0 +1,44 @@ +{ + "$type": "social.coves.community.rules", + "postTypes": { + "allowText": true, + "allowVideo": true, + "allowImage": true, + "allowArticle": true + }, + "contentRestrictions": { + "blockedDomains": ["spam.com", "malware.com"], + "allowedDomains": [] + }, + "geoRestrictions": { + "enabled": true, + "allowedCountries": ["US", "CA", "GB", "AU"], + "allowedRegions": [] + }, + "customTags": ["help", "announcement", "discussion", "tutorial"], + "textRules": [ + { + "title": "Be respectful", + "description": "Treat all members with respect. No harassment, hate speech, or personal attacks.", + "createdAt": "2024-01-01T00:00:00Z", + "isActive": true + }, + { + "title": "No spam", + "description": "Do not post spam, including excessive self-promotion or irrelevant content.", + "createdAt": "2024-01-01T00:00:00Z", + "isActive": true + }, + { + "title": "Stay on topic", + "description": "Posts must be related to programming and software development.", + "createdAt": "2024-01-01T00:00:00Z", + "isActive": true + } + ], + "sortitionConfig": { + "tagThreshold": 15, + "tribunalThreshold": 30, + "jurySize": 9 + } +} \ No newline at end of file diff --git a/tests/lexicon-test-data/community/wiki-invalid-slug.json b/tests/lexicon-test-data/community/wiki-invalid-slug.json new file mode 100644 index 0000000..a286069 --- /dev/null +++ b/tests/lexicon-test-data/community/wiki-invalid-slug.json @@ -0,0 +1,7 @@ +{ + "$type": "social.coves.community.wiki", + "slug": "this-slug-is-way-too-long-and-exceeds-the-maximum-allowed-length-of-128-characters-which-should-trigger-a-validation-error-when-we-run-the-test", + "title": "Invalid Wiki Page", + "content": "This wiki page has a slug that exceeds the maximum length.", + "createdAt": "2024-01-01T00:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/community/wiki-valid.json b/tests/lexicon-test-data/community/wiki-valid.json new file mode 100644 index 0000000..5c9d2cb --- /dev/null +++ b/tests/lexicon-test-data/community/wiki-valid.json @@ -0,0 +1,13 @@ +{ + "$type": "social.coves.community.wiki", + "slug": "getting-started", + "title": "Getting Started with Our Community", + "content": "# Welcome to the Programming Community\n\nThis guide will help you get started with our community.\n\n## Rules\nPlease read our community rules before posting.\n\n## Resources\n- [FAQ](/wiki/faq)\n- [Posting Guidelines](/wiki/posting-guidelines)\n- [Code of Conduct](/wiki/code-of-conduct)", + "author": "did:plc:moderator123", + "editors": ["did:plc:editor1", "did:plc:editor2"], + "isIndex": false, + "createdAt": "2024-01-01T00:00:00Z", + "updatedAt": "2025-01-09T15:00:00Z", + "revision": 5, + "tags": ["meta", "help", "guide"] +} \ No newline at end of file diff --git a/tests/lexicon-test-data/interaction/comment-invalid-content.json b/tests/lexicon-test-data/interaction/comment-invalid-content.json new file mode 100644 index 0000000..8619cbe --- /dev/null +++ b/tests/lexicon-test-data/interaction/comment-invalid-content.json @@ -0,0 +1,5 @@ +{ + "$type": "social.coves.interaction.comment", + "post": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", + "createdAt": "2025-01-09T16:45:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/interaction/comment-valid-sticker.json b/tests/lexicon-test-data/interaction/comment-valid-sticker.json new file mode 100644 index 0000000..1e1e24c --- /dev/null +++ b/tests/lexicon-test-data/interaction/comment-valid-sticker.json @@ -0,0 +1,10 @@ +{ + "$type": "social.coves.interaction.comment", + "subject": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", + "content": { + "$type": "social.coves.interaction.comment#stickerContent", + "stickerId": "thumbs-up", + "stickerPackId": "default-pack" + }, + "createdAt": "2025-01-09T16:50:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/interaction/comment-valid-text.json b/tests/lexicon-test-data/interaction/comment-valid-text.json new file mode 100644 index 0000000..a71c434 --- /dev/null +++ b/tests/lexicon-test-data/interaction/comment-valid-text.json @@ -0,0 +1,23 @@ +{ + "$type": "social.coves.interaction.comment", + "subject": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", + "content": { + "$type": "social.coves.interaction.comment#textContent", + "text": "Great post! I especially liked the part about @alice.example.com's contribution to the project.", + "facets": [ + { + "index": { + "byteStart": 46, + "byteEnd": 64 + }, + "features": [ + { + "$type": "social.coves.richtext.facet#mention", + "did": "did:plc:aliceuser123" + } + ] + } + ] + }, + "createdAt": "2025-01-09T16:30:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/interaction/share-valid-no-community.json b/tests/lexicon-test-data/interaction/share-valid-no-community.json new file mode 100644 index 0000000..f631297 --- /dev/null +++ b/tests/lexicon-test-data/interaction/share-valid-no-community.json @@ -0,0 +1,5 @@ +{ + "$type": "social.coves.interaction.share", + "subject": "at://did:plc:originalauthor/social.coves.post.record/3k7a3dmb5bk2c", + "createdAt": "2025-01-09T17:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/interaction/share-valid.json b/tests/lexicon-test-data/interaction/share-valid.json new file mode 100644 index 0000000..6488ec5 --- /dev/null +++ b/tests/lexicon-test-data/interaction/share-valid.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.interaction.share", + "subject": "at://did:plc:originalauthor/social.coves.post.record/3k7a3dmb5bk2c", + "community": "did:plc:targetcommunity", + "createdAt": "2025-01-09T17:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/interaction/tag-invalid-empty.json b/tests/lexicon-test-data/interaction/tag-invalid-empty.json new file mode 100644 index 0000000..ca15543 --- /dev/null +++ b/tests/lexicon-test-data/interaction/tag-invalid-empty.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.interaction.tag", + "subject": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", + "tag": "", + "createdAt": "2025-01-09T17:15:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/interaction/tag-valid-custom.json b/tests/lexicon-test-data/interaction/tag-valid-custom.json new file mode 100644 index 0000000..b3967f5 --- /dev/null +++ b/tests/lexicon-test-data/interaction/tag-valid-custom.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.interaction.tag", + "subject": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", + "tag": "beginner-friendly", + "createdAt": "2025-01-09T17:15:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/interaction/tag-valid-known.json b/tests/lexicon-test-data/interaction/tag-valid-known.json new file mode 100644 index 0000000..54bf67e --- /dev/null +++ b/tests/lexicon-test-data/interaction/tag-valid-known.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.interaction.tag", + "subject": "at://did:plc:author123/social.coves.post.record/3k7a3dmb5bk2c", + "tag": "nsfw", + "createdAt": "2025-01-09T17:15:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/moderation/rule-proposal-invalid-status.json b/tests/lexicon-test-data/moderation/rule-proposal-invalid-status.json new file mode 100644 index 0000000..4ff7282 --- /dev/null +++ b/tests/lexicon-test-data/moderation/rule-proposal-invalid-status.json @@ -0,0 +1,9 @@ +{ + "$type": "social.coves.moderation.ruleProposal", + "community": "did:plc:community123", + "proposalType": "addRule", + "title": "Test invalid status", + "description": "This should fail validation due to invalid status", + "status": "invalidStatus", + "createdAt": "2025-01-09T17:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/moderation/rule-proposal-invalid-threshold.json b/tests/lexicon-test-data/moderation/rule-proposal-invalid-threshold.json new file mode 100644 index 0000000..29d9573 --- /dev/null +++ b/tests/lexicon-test-data/moderation/rule-proposal-invalid-threshold.json @@ -0,0 +1,9 @@ +{ + "$type": "social.coves.moderation.ruleProposal", + "community": "did:plc:community123", + "proposalType": "updateRule", + "title": "Update harassment policy", + "description": "Strengthen the harassment policy", + "requiredVotes": -50, + "createdAt": "2025-01-09T17:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/moderation/rule-proposal-invalid-type.json b/tests/lexicon-test-data/moderation/rule-proposal-invalid-type.json new file mode 100644 index 0000000..722a091 --- /dev/null +++ b/tests/lexicon-test-data/moderation/rule-proposal-invalid-type.json @@ -0,0 +1,8 @@ +{ + "$type": "social.coves.moderation.ruleProposal", + "community": "did:plc:community123", + "proposalType": "invalidProposalType", + "title": "Test invalid proposal type", + "description": "This should fail validation", + "createdAt": "2025-01-09T17:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/moderation/rule-proposal-valid.json b/tests/lexicon-test-data/moderation/rule-proposal-valid.json new file mode 100644 index 0000000..b0d38c7 --- /dev/null +++ b/tests/lexicon-test-data/moderation/rule-proposal-valid.json @@ -0,0 +1,13 @@ +{ + "$type": "social.coves.moderation.ruleProposal", + "community": "did:plc:programmingcommunity", + "proposalType": "addRule", + "title": "No AI-generated content without disclosure", + "description": "All AI-generated code or content must be clearly marked as such. This helps maintain transparency and allows community members to make informed decisions about the content they consume.", + "proposalData": { + "ruleTitle": "Disclose AI-generated content", + "ruleDescription": "All posts containing AI-generated code or content must include a clear disclosure statement" + }, + "requiredVotes": 100, + "createdAt": "2025-01-09T17:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/moderation/tribunal-vote-invalid-decision.json b/tests/lexicon-test-data/moderation/tribunal-vote-invalid-decision.json new file mode 100644 index 0000000..bb78a31 --- /dev/null +++ b/tests/lexicon-test-data/moderation/tribunal-vote-invalid-decision.json @@ -0,0 +1,7 @@ +{ + "$type": "social.coves.moderation.tribunalVote", + "tribunal": "at://did:plc:community123/social.coves.moderation.tribunal/3k7a3dmb5bk2c", + "subject": "at://did:plc:user123/social.coves.post.record/3k7a2clb4bj2b", + "decision": "maybe", + "createdAt": "2025-01-09T18:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/moderation/tribunal-vote-valid.json b/tests/lexicon-test-data/moderation/tribunal-vote-valid.json new file mode 100644 index 0000000..b6087a4 --- /dev/null +++ b/tests/lexicon-test-data/moderation/tribunal-vote-valid.json @@ -0,0 +1,13 @@ +{ + "$type": "social.coves.moderation.tribunalVote", + "tribunal": "at://did:plc:community123/social.coves.moderation.tribunal/3k7a3dmb5bk2c", + "subject": "at://did:plc:spammer123/social.coves.post.record/3k7a2clb4bj2b", + "decision": "remove", + "reasoning": "The moderator's action was justified based on clear violation of Rule 2 (No Spam). The user posted the same promotional content across multiple communities within a short timeframe.", + "precedents": [ + "at://did:plc:community123/social.coves.moderation.case/3k6z2cla4aj1a", + "at://did:plc:community456/social.coves.moderation.case/3k6y1bkz3zi0z" + ], + "dissenting": false, + "createdAt": "2025-01-09T18:00:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/moderation/vote-invalid-option.json b/tests/lexicon-test-data/moderation/vote-invalid-option.json new file mode 100644 index 0000000..e6ff44f --- /dev/null +++ b/tests/lexicon-test-data/moderation/vote-invalid-option.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.moderation.vote", + "subject": "at://did:plc:community123/social.coves.moderation.ruleProposal/3k7a3dmb5bk2c", + "vote": "strongly-approve", + "createdAt": "2025-01-09T18:30:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/moderation/vote-valid-approve.json b/tests/lexicon-test-data/moderation/vote-valid-approve.json new file mode 100644 index 0000000..d3e1361 --- /dev/null +++ b/tests/lexicon-test-data/moderation/vote-valid-approve.json @@ -0,0 +1,6 @@ +{ + "$type": "social.coves.moderation.vote", + "subject": "at://did:plc:community123/social.coves.moderation.ruleProposal/3k7a3dmb5bk2c", + "vote": "approve", + "createdAt": "2025-01-09T18:30:00Z" +} \ No newline at end of file diff --git a/tests/lexicon-test-data/post/post-invalid-missing-community.json b/tests/lexicon-test-data/post/post-invalid-missing-community.json new file mode 100644 index 0000000..34ba2b5 --- /dev/null +++ b/tests/lexicon-test-data/post/post-invalid-missing-community.json @@ -0,0 +1,10 @@ +{ + "$type": "social.coves.post.record", + "postType": "text", + "title": "Test Post", + "text": "This post is missing the required community field", + "tags": ["test"], + "language": "en", + "contentWarnings": [], + "createdAt": "2025-01-09T14:30:00Z" +} \ No newline at end of file