···11+# Mezzanine Lexicons
22+33+ATProto-native Lexicon definitions for [Mezzanine (中2階)](https://plurality.leaflet.pub), an information networking system using opaque cashtag connectors on Bluesky.
44+55+## Overview
66+77+Mezzanine repurposes Bluesky's cashtag feature (`$` + alphanumeric string) as opaque connectors — they point without signifying. This repository defines ATProto Lexicon schemas to move Mezzanine from a text-convention layer to a protocol-native system.
88+99+## Namespace
1010+1111+`blue.moja.mezzanine.*`
1212+1313+## Architecture
1414+1515+### Phase 1: Annotation Layer (current)
1616+1717+Mezzanine operates as a metadata layer over standard `app.bsky.feed.post` records. Users post normally on Bluesky; a separate `blue.moja.mezzanine.tag` record annotates each post with its channel and role.
1818+1919+This is analogous to how `app.bsky.feed.like` annotates posts without modifying them.
2020+2121+| Lexicon | Type | Purpose |
2222+|---------|------|---------|
2323+| `blue.moja.mezzanine.defs` | defs | Shared types: channel tag format, post role enum |
2424+| `blue.moja.mezzanine.channel` | record | Channel definition (tag + metadata) |
2525+| `blue.moja.mezzanine.tag` | record | Post-to-channel annotation (subject + tag + role) |
2626+2727+### Phase 2: Native Post Type (future)
2828+2929+A dedicated `blue.moja.mezzanine.post` record type with its own AppView and feed generator. This would allow Mezzanine posts to exist independently of Bluesky's post schema.
3030+3131+## Mezzanine Spec
3232+3333+The full Mezzanine specification is maintained at:
3434+- [mezzanine-spec-v2.1.1.md](./mezzanine-spec-v2.1.1.md) (snapshot in this repo)
3535+- [Nightflight blog](https://plurality.leaflet.pub) (canonical)
3636+3737+## Channel Tags
3838+3939+Tags are 3–5 alphanumeric characters. First character must be alphabetic. Must contain at least one digit (to avoid collision with stock ticker symbols). Case-insensitive.
4040+4141+Current official channels:
4242+4343+| Tag | Purpose |
4444+|-----|---------|
4545+| `cT7aZ` | Anchor (meta/system) |
4646+| `ATOPR` | AT Protocol ecosystem |
4747+| `sT3m0` | STEM |
4848+| `L1f3x` | Life |
4949+| `cLt7r` | Culture |
5050+5151+## License
5252+5353+CC0 — Mezzanine concepts and schemas are free to use, modify, and redistribute.
+45
lexicons/blue/moja/mezzanine/channel.json
···11+{
22+ "lexicon": 1,
33+ "id": "blue.moja.mezzanine.channel",
44+ "description": "A Mezzanine channel definition. Channels are named by opaque cashtag anchors and serve as frequency-based connectors, not semantic categories.",
55+ "defs": {
66+ "main": {
77+ "type": "record",
88+ "description": "Record representing a Mezzanine channel owned by the creating account.",
99+ "key": "tid",
1010+ "record": {
1111+ "type": "object",
1212+ "required": ["tag", "createdAt"],
1313+ "properties": {
1414+ "tag": {
1515+ "type": "ref",
1616+ "ref": "blue.moja.mezzanine.defs#channelTag",
1717+ "description": "The cashtag anchor for this channel (without the '$' prefix)."
1818+ },
1919+ "label": {
2020+ "type": "string",
2121+ "maxLength": 64,
2222+ "description": "Optional human-readable label for the channel. Semi-transparent tags may use this for discoverability."
2323+ },
2424+ "description": {
2525+ "type": "string",
2626+ "maxLength": 300,
2727+ "description": "Optional description of the channel's theme or purpose."
2828+ },
2929+ "visibility": {
3030+ "type": "string",
3131+ "description": "Channel visibility. 'public' channels are discoverable; 'unlisted' channels require knowing the tag.",
3232+ "knownValues": [
3333+ "public",
3434+ "unlisted"
3535+ ]
3636+ },
3737+ "createdAt": {
3838+ "type": "string",
3939+ "format": "datetime"
4040+ }
4141+ }
4242+ }
4343+ }
4444+ }
4545+}
+21
lexicons/blue/moja/mezzanine/defs.json
···11+{
22+ "lexicon": 1,
33+ "id": "blue.moja.mezzanine.defs",
44+ "description": "Shared definitions for the Mezzanine information networking system.",
55+ "defs": {
66+ "channelTag": {
77+ "type": "string",
88+ "description": "A Mezzanine channel tag: 3-5 alphanumeric characters, first character must be alphabetic, must contain at least one digit to avoid collision with stock ticker symbols. Case-insensitive.",
99+ "minLength": 3,
1010+ "maxLength": 5
1111+ },
1212+ "postRole": {
1313+ "type": "string",
1414+ "description": "The role of a post within its channel. 'top' indicates an entry point; 'support' indicates supplementary content.",
1515+ "knownValues": [
1616+ "top",
1717+ "support"
1818+ ]
1919+ }
2020+ }
2121+}
+37
lexicons/blue/moja/mezzanine/tag.json
···11+{
22+ "lexicon": 1,
33+ "id": "blue.moja.mezzanine.tag",
44+ "description": "An annotation record that links an existing app.bsky.feed.post to a Mezzanine channel. This is the Phase 1 approach: Mezzanine as a metadata layer over standard Bluesky posts, analogous to how likes and reposts annotate posts without modifying them.",
55+ "defs": {
66+ "main": {
77+ "type": "record",
88+ "description": "Associates a Bluesky post with a Mezzanine channel tag and role.",
99+ "key": "tid",
1010+ "record": {
1111+ "type": "object",
1212+ "required": ["subject", "tag", "role", "createdAt"],
1313+ "properties": {
1414+ "subject": {
1515+ "type": "ref",
1616+ "ref": "com.atproto.repo.strongRef",
1717+ "description": "Reference to the app.bsky.feed.post being annotated."
1818+ },
1919+ "tag": {
2020+ "type": "ref",
2121+ "ref": "blue.moja.mezzanine.defs#channelTag",
2222+ "description": "The cashtag anchor (without '$' prefix) linking this post to a channel."
2323+ },
2424+ "role": {
2525+ "type": "ref",
2626+ "ref": "blue.moja.mezzanine.defs#postRole",
2727+ "description": "Whether this post is a 'top' (entry point) or 'support' (supplementary) post in the channel."
2828+ },
2929+ "createdAt": {
3030+ "type": "string",
3131+ "format": "datetime"
3232+ }
3333+ }
3434+ }
3535+ }
3636+ }
3737+}