Mastic uses wasm-dbms for persistent
storage inside the Directory and User canisters. Because wasm-dbms manages its
own stable memory, ic-stable-structures cannot be used alongside it in these
canisters. Configuration values that would normally live in stable cells are
stored in a shared settings key-value table instead.
The Federation Canister does not use wasm-dbms; it uses
ic-stable-structures directly.
Both the Directory and User canisters include a settings table with the same
schema. Each row maps an integer key to a polymorphic value
(SettingValue, backed by the wasm-dbms Value type).
Column Type Constraint Description
keyUINT16PRIMARY KEY Setting identifier
valueSettingValueTyped value for the entry
The Settings table and its helper methods (set_config_key,
get_required_settings_value, get_settings_value, get_as_principal) live in
the db-utils crate and are shared by both canisters.
Key Constant Value Type Description
0SETTING_FEDERATION_CANISTERBLOBPrincipal of the Federation canister
Column Type Constraint Description
principalPrincipalPRIMARY KEY The moderator’s principal
created_atUINT64Timestamp when added
Column Type Constraint Description
principalPrincipalPRIMARY KEY The user’s principal
handleTEXTUNIQUE, validated User’s unique handle
canister_idNullable<Principal>UNIQUE User Canister ID
canister_statusCanisterStatusActive, CreationPending, …
created_atUINT64Timestamp when registered
The handle column uses HandleSanitizer (trims whitespace, lowercases,
strips leading @) and HandleValidator (enforces the
handle rules ). See the Handle Validation page
for the full specification.
Retains deleted handles to block immediate re-registration and to keep
an audit trail. handle uses the same sanitizer/validator pair as the
users.handle column; see the Handle Validation spec.
Column Type Constraint Description
handleTEXTPRIMARY KEY, sanitized, validated Handle of the deleted user
principalPrincipalPrincipal of the deleted user
deleted_atUINT64Timestamp when the user was deleted
Stores user-submitted moderation reports. See the
Reports spec for validation rules on reason
and target_status_uri.
Column Type Constraint Description
idUINT64PRIMARY KEY Snowflake ID
reporterPrincipalPrincipal of the reporter
target_canisterPrincipalReported user’s canister principal
target_status_uriNullable<Text>validated URI of the reported status, if any
reasonTEXTsanitized, validated Free-form reason
stateReportStateOpen, Resolved, Dismissed
created_atUINT64INDEX Submission timestamp
resolved_atNullable<Uint64>Timestamp when the report was resolved
resolved_byNullable<Principal>Moderator who resolved the report
Key Constant Value Type Description
0SETTING_FEDERATION_CANISTERBLOBPrincipal of the Federation canister
1SETTING_OWNER_PRINCIPALBLOBPrincipal of the canister owner
2SETTING_PUBLIC_URLTEXTPublic URL of the Mastic instance
3SETTING_DIRECTORY_CANISTERBLOBPrincipal of the Directory canister
Single-row table holding the owner’s profile.
Column Type Constraint Description
principalPrincipalPRIMARY KEY Owner’s principal
handleTEXTUNIQUE, validated User’s unique handle
display_nameNullable<Text>Display name
bioNullable<Text>Biography
avatar_dataNullable<Blob>Avatar image data
header_dataNullable<Blob>Header / banner data
created_atUINT64Account creation time
updated_atUINT64Last profile update
See the Status Content spec for full validation
rules on content, spoiler_text, and in_reply_to_uri.
Column Type Constraint Description
idUINT64PRIMARY KEY Snowflake ID
contentTEXTvalidated Status body
visibilityVisibilityPublic, Unlisted, FollowersOnly, Direct
like_countUINT64Cached Like count
boost_countUINT64Cached Announce (boost) count
in_reply_to_uriNullable<Text>INDEX, validated URI of the replied-to status
spoiler_textNullable<Text>sanitized, validated Optional content warning / spoiler
sensitiveBooleanWhether clients should hide behind a CW
edited_atNullable<Uint64>Timestamp of the last edit
created_atUINT64INDEX Creation timestamp (indexed for feed ordering)
Stores inbound ActivityPub activities.
Column Type Constraint Description
idUINT64PRIMARY KEY Snowflake ID
activity_typeActivityTypeActivity discriminator (Create, Follow, …)
actor_uriTEXTvalidated Originating actor’s URI
object_dataJSONActivity object payload
is_boostBooleantrue when entry is an Announce (boost)
original_status_uriNullable<Text>validated URI of the boosted status
created_atUINT64INDEX Reception timestamp (indexed for feed ordering)
Column Type Constraint Description
actor_uriTEXTPRIMARY KEY Requester’s actor URI
created_atUINT64Timestamp when follow request received
Column Type Constraint Description
actor_uriTEXTPRIMARY KEY Follower’s actor URI
created_atUINT64Timestamp when follow accepted
Column Type Constraint Description
actor_uriTEXTPRIMARY KEY Followed actor’s URI
statusFollowStatusPending or Accepted (rejected entries are deleted)
created_atUINT64Timestamp when follow was requested
Column Type Constraint Description
status_uriTEXTPRIMARY KEY, validated URI of the liked status
created_atUINT64Timestamp when the status was liked
Column Type Constraint Description
actor_uriTEXTPRIMARY KEY, validated URI of the blocked actor
created_atUINT64Timestamp when block was added
Column Type Constraint Description
actor_uriTEXTPRIMARY KEY, validated URI of the muted actor
created_atUINT64Timestamp when mute was added
Column Type Constraint Description
status_uriTEXTPRIMARY KEY, validated URI of the bookmarked status
created_atUINT64Timestamp when bookmark was set
Tracks Announce activities emitted by the user. Each boost is
paired with a wrapper row in the statuses table.
Column Type Constraint Description
idUINT64PRIMARY KEY Snowflake ID
status_idUINT64FK → statuses.id Wrapper status row
original_status_uriTEXTvalidated URI of the boosted status
created_atUINT64INDEX Timestamp when the boost was emitted
The same Snowflake is reused as boosts.id, boosts.status_id, the
wrapper statuses.id, and the wrapper’s feed.id — making the
wrapper status URL <actor>/statuses/<snowflake> also the canonical
id of the emitted Announce activity. One sequence increment per
boost; one URL that dereferences both the wrapper status and the boost
activity.
See the Media Attachments spec for full validation
rules on media_type, description, and blurhash.
Column Type Constraint Description
idUINT64PRIMARY KEY Snowflake ID
status_idUINT64FK → statuses.id, INDEX Parent status
media_typeTEXTvalidated MIME-like media type
descriptionNullable<Text>sanitized, validated Alt-text description
blurhashNullable<Text>validated Blurhash preview string
bytesBLOBRaw media bytes
created_atUINT64Creation timestamp
previous_spoiler_text uses the same sanitizer/validator pair as
statuses.spoiler_text; see the Status Content
spec.
Column Type Constraint Description
idUINT64PRIMARY KEY Snowflake ID
status_idUINT64FK → statuses.id, INDEX Status this entry belongs to
previous_contentTEXTContent before the edit
previous_spoiler_textNullable<Text>sanitized, validated Spoiler text before the edit
edited_atUINT64INDEX Timestamp of the edit
Local per-user index of hashtags referenced by the user’s statuses.
Column Type Constraint Description
idUINT64PRIMARY KEY Snowflake ID
tagTEXTUNIQUE, validated Sanitized, lowercase tag (without #)
created_atUINT64Timestamp when the hashtag was first seen
The tag column uses HashtagSanitizer (trims whitespace, lowercases,
strips leading #) and HashtagValidator. See the
Hashtag Validation page for the full
specification.
Join table between statuses and hashtags. Uses a surrogate id
primary key because the underlying storage layer does not support
composite primary keys; uniqueness of (status_id, hashtag_id) is
enforced by the application layer.
Column Type Constraint Description
idUINT64PRIMARY KEY Snowflake ID
status_idUINT64FK → statuses.id, INDEX Status
hashtag_idUINT64FK → hashtags.id, INDEX Hashtag
Up to four hashtags featured on the user’s profile. The tag column
uses the same HashtagSanitizer / HashtagValidator
pair as the hashtags table.
Column Type Constraint Description
tagTEXTPRIMARY KEY, validated Sanitized, lowercase tag
positionUINT8UNIQUE (0..=3) Display position
created_atUINT64Timestamp when tag was featured
Up to five statuses pinned on the user’s profile.
Column Type Constraint Description
status_idUINT64PRIMARY KEY, FK → statuses.id Pinned status
positionUINT8UNIQUE (0..=4) Display position
pinned_atUINT64Timestamp when status was pinned
Up to four custom fields shown on the user’s profile. See the
Profile Metadata spec for full
validation rules.
Column Type Constraint Description
positionUINT8PRIMARY KEY (0..=3) Position in the list
nameTEXTsanitized, validated Field name
valueTEXTsanitized, validated Field value
The following custom types are used in the schema and stored as compact
single-byte discriminants:
Maps to did::common::Visibility .
Value Variant
0Public
1Unlisted
2FollowersOnly
3Direct
Maps to activitypub::ActivityType.
Value Variant
0Create
1Update
2Delete
3Follow
4Accept
5Reject
6Like
7Announce
8Undo
9Block
10Add
11Remove
12Flag
13Move
Value Variant
0Pending
1Accepted
Value Variant
0Open
1Resolved
2Dismissed
All tables are created during canister init. Data survives canister upgrades
because wasm-dbms stores everything in stable memory. The post_upgrade
function does not need to re-register the schema.