/// <spock> language specification 2026, original author universe @softmarshmallow
/// reserved tokens: iam, role, model, volatile, trait, and, pub, mut, once, fn, extends, @identity, @frequency, @protected, @default, for, materialized
/// std modules: auth, storage
/// key considerations: ergonomics, performance, security
role user extends auth::user;
role visitor exetnds auth::anon;
role post_author extends user on model::post {
role community_owner extends user on model::community {
format username extends text {
check: regex("^[a-zA-Z0-9_-]{3,16}$")
error ERR_USERNAME_ALREADY_EXISTS extends UNIQUE_CONSTRAINTS_CONFLICT {
"this username is already taken"
// username can't be directly changed
pub username: username @protected
pub view user_profile for role::visitor {
pub fn check_username_available {
pub fn change_username over model::user_profile unlocks .username {
cover_image: storage::object
created_at: timestamp @createdat
mut cover_image: .cover_image
user: auth::user @identity
@identity(user, community)
format tag extends text {
check: regex("#\w{2,10}\b")
community: community @protected
author: auth::user @protected
created_at: timestamp @createdat
updated_at: timestamp @updatedat
is_draft: bool @default(false) @draft
pub view post respects draft {
format comment_body extends text {
check: regex("^[^\\n\\r]*$")
author: auth::user @protected
created_at: timestamp @createdat
is_deleted: bool @default(false) @softdelete
pub view post_comment respects softdelete {
count_upvotes: int @materialized
count_downvotes: int @materialized
enum VoteStatus { none = 0, up = 1, down = 2 }
trait votes for model::post, model::post_comment {
// effects for votes counter
effect on_votes_bit_change for votes {
let current_vote_kind = vote_kind
pub volatile fn upvote for votes over model::post, model::post_comment with effect on_votes_bit_change {
pub volatile fn downvote for votes over model::post, model::post_comment with effect on_votes_bit_change {
pub volatile fn unvote for votes over model::post, model::post_comment with effect on_votes_bit_change {
describe("only community owner can invite new admin") {
describe("user profile to be auto inserted as user sign up"){