| Database | User | |
|---|---|---|
| Purpose | Hold a member's public profile and the topics they create. | |
| Cardinality | exactly one User database per member one NextTopicItemin each User databaseone VerifyItemin each User databaseone EscrowUserItemin each User database for members who haven't accepted their invitationone ProfileItemin each User databaseone TopicItemitem per topic made by the member | |
| Source Code | ||
| Items | src/ts/dbitems/User.ts | |
| Zod Models | ||
| item | UserItem- union ofNextTopicItem,VerifyItem,EscrowUserItem,ProfileItem,TopicItembelow | |
| item.item | one of NextTopicRecord,VerifyRecord,EscrowUserRecord,ProfileRecord,TopicRecord | |
| NextTopicItem | ||
| itemId | 'nexttopic' | |
| item: | NextTopicRecord | |
| kind | 'nexttopic' | |
| mnum | this member's member number | |
| nexttnum | next topic number to assign (first is 1) | |
| VerifyItem | ||
| itemId | 'verify' | |
| item: | VerifyRecord | |
| kind | 'verify' | |
| mnum | this member's member number | |
| message | Userbase verification message for user | |
| EscrowUserItem | ||
| itemId | 'escrowuser' | |
| item: | EscrowUserRecord | |
| kind | 'escrowuser' | |
| mnum | this member's member number | |
| message | Userbase verification message for ESCROW user | |
| username | Userbase username for ESCROW user | |
| ProfileItem | ||
| itemId | 'profile' | |
| item: | ProfileRecord | |
| kind | 'profile' | |
| mnum | this member's member number | |
| hasThumbnail | true if item has associated thumbnail stored as a file | |
| initials | member's initials | |
| title | member's title | |
| subtitle | optional member's subtitle | |
| paragraph | optional member's paragraph | |
| moniker | member's moniker | |
| accepted_on | posix millis utc when invitation accepted (0 if not) | |
| home | optional ProfileHomeTopicorProfileHomeBundleindicating page member should see after joining | |
| ProfileHomeTopic | ||
| kind | 'home topic' | |
| tkey | topic member should see after joining | |
| ProfileHomeBundle | ||
| kind | 'home bundle' | |
| bnum | bundle member should see after joining | |
| TopicItem | ||
| itemId | topic key (creator ++ transliterated topic number) | |
| item: | TopicRecord | |
| kind | 'topic' | |
| mnum | this member's member number | |
| tnum | this topic's topic number | |
| tid | TID of the topic, used as prefix for TID-Topic database name | |
| dbid | dbid of the corresponding TID-Topic database | |
Description
A User database is created when the host creates an engagement or invites a new member to the engagement.
It holds one NextTopicItem to track the number of the next topic created by the member.
It holds one VerifyItem for the member's Userbase verification message.
                It holds one EscrowUserItem for an invited member's ESCROW user Userbase verification message and username.
              
It holds one ProfileItem for the member's profile.
It holds one TopicItem for each discussion topic created by the member.
(see userbase-js/types/index.d.ts)
  export interface Item {              userbase item
    itemId: string                    ╭─────────────────────┐
    item: any ────────────────────┬──▶│ kind: 'nexttopic'   │
    createdBy: Attribution        │   │ nexttnum: 1         │
    updatedBy?: Attribution       │   ╰─────────────────────┘
    fileId?: string               │
    fileName?: string             │   ╭────────────────────────────────────────┐
    fileSize?: number             ├──▶│ kind: 'verify'                         │
    fileUploadedBy?: Attribution  │   │ messgage: 'mFtZSI6IjeyJ1c2Vyb...'      │
    writeAccess?: AccessControl   │   ╰────────────────────────────────────────┘
  }                               │
                                  │   ╭────────────────────────────────────────┐
                                  ├──▶│ kind: 'escrowuser'                     │
                                  │   │ mnum: 2                                │
                                  │   │ message:  'eyJ1c2VybmFtZSI6Inl...'     │
                                  │   │ username: '01hss3d1pj3e0bvhy8khcqeys6' │
                                  │   ╰────────────────────────────────────────┘
                                  │
                                  │   ╭─────────────────────┐    file
                                  ├──▶│ kind: 'profile'     │   ┌────────────────┐
                                  │   │ mnum: 2             │╶╶ │ thumbnail data │
                                  │   │ hasThumbnail: true  │   └────────────────┘
                                  │   │ ...                 │
                                  │   ╰─────────────────────┘
                                  │
                                  │   ╭────────────────────────────────────────┐
                                  └──▶│ kind: 'topic'                          │
                                      │ mnum: 2                                │
                                      │ tnum: 1                                │
                                      │ tid:  'THFVJ01H6ETV4ZBRQFXMMRX23G'     │
                                      │ dbid: 'G32XRMMFHTXFQRBZ4VTE6H10JV'     │
                                      ╰────────────────────────────────────────┘
UserItem represents the specific type of Item.item:
  NextTopicItem, VerifyItem, EscrowUserItem, ProfileItem or TopicItem.
              NextTopicItem
                Each member's User database has a single NextTopicItem which holds a serial 'next topic' number which
                starts with 1 and is incremented each time the member creates a topic.
              
VerifyItem
                Each member's User database has a single VerifyItem which holds the user's Userbase verification message
                which is set when the member is added and updated each time the member changes their userbase information.
              
EscrowUserItem
                The User database of each member who has not accepted their invitation has a single EscrowUserItem which
                holds the member's escrow user Userbase verification message and username which is set when the member is added.
              
The EscrowUserItem is removed when a user accepts their invitation.
ProfileItem
                Each member's User database has a ProfileItem with a few identifying facts shared with other members.
                The profile facts are initially set by the host when the member is invited. A member can change the facts after they've
                accepted the invitation.
              
TopicItem
                Each member's User database has a TopicItem for each topic the member creates. The TopicItem identifies
                the TID-Topic database with the topic's details and members.
              
                The itemId of the TopicItem, also known as the tkey, is the concatenation of the digits of the
                member number of the topic's creator and the digits of the topic number transliterated as follows
              
    0 1 2 3 4 5 6 7 8 9 
    │ │ │ │ │ │ │ │ │ │ 
    ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ 
    Z A B C D E F G H J 
              For example "3B" indicates the second topic (B) created by member 3.
Ownership and Access
The member is the owner of their User database.
Other members in the engagement have read permission to the member's User database.
Zod models
The following Zod models show how the Userbase items are represented in memory.
export type UserItem =
  | NextTopicItem
  | VerifyItem
  | EscrowUserItem
  | ProfileItem
  | TopicItem
;
export const UserItem = z.discriminatedUnion('kind', [
  NextTopicItem,
  VerifyItem,
  EscrowUserItem,
  ProfileItem,
  TopicItem
]);
NextTopicItem
In addition to the values specified by the Userbase Item interface the kind and database attributes are added to NextTopicItem during deserialization.
export type  NextTopicItem = z.infer<typeof NextTopicItem>;
export const NextTopicItem = z.object({
  kind:                 z.literal('nexttopicitem'),
  itemId:               z.string(),
  item:                 NextTopicRecord,
  updatedBy:            z.custom<Attribution>(),
  database:             z.custom<Database>()
}).strip();
export type  NextTopicRecord = z.infer<typeof NextTopicRecord>;
export const NextTopicRecord = z.object({
  kind:                 z.literal('nexttopic'),
  mnum:                 z.number(),
  nexttnum:             z.number(),
}).strip();
VerifyItem
                In addition to the values specified by the Userbase Item interface the kind and
                database attributes are added to VerifyItem during deserialization.
              
export type  VerifyItem = z.infer<typeof VerifyItem>;
export const VerifyItem = z.object({
  kind:                 z.literal('verifyitem'),
  itemId:               z.string(),
  item:                 VerifyRecord,
  updatedBy:            z.custom<Attribution>(),
  database:             z.custom<Database>()
}).strip();
export type  VerifyRecord = z.infer<typeof VerifyRecord>;
export const VerifyRecord = z.object({
  kind:                 z.literal('verify'),
  mnum:                 z.number(),
  message:              z.string()
}).strip();
EscrowUserItem
                In addition to the values specified by the Userbase Item interface the kind and
                database attributes are added to EscrowUserItem during deserialization.
              
export type  EscrowUserItem = z.infer<typeof EscrowUserItem>;
export const EscrowUserItem = z.object({
  kind:                 z.literal('escrowuseritem'),
  itemId:               z.string(),
  item:                 EscrowUserRecord,
  updatedBy:            z.custom<Attribution>(),
  database:             z.custom<Database>()
}).strip();
export type  EscrowUserRecord = z.infer<typeof EscrowUserRecord>;
export const EscrowUserRecord = z.object({
  kind:                 z.literal('escrowuser'),
  mnum:                 z.number(),
  message:              z.string(),
  username:             z.string()
}).strip();
ProfileItem
                In addition to the values specified by the Userbase Item interface the kind, database and
                thumbnail attributes are added to ProfileItem during deserialization.
              
export type  ProfileItem = z.infer<typeof ProfileItem>;
export const ProfileItem = z.object({
  kind:                 z.literal('profileitem'),
  fileId:               z.string().optional(),
  itemId:               z.string(),
  item:                 ProfileRecord,
  updatedBy:            z.custom<Attribution>(),
  database:             z.custom<Database>(),
  thumbnail:            z.string().optional()
}).strip();
export type  ProfileRecord = z.infer<typeof ProfileRecord>;
export const ProfileRecord = z.object({
  kind:                 z.literal('profile'),
  mnum:                 z.number(),
  hasThumbnail:         z.boolean(), //thumbnail stored as a file?
  initials:             z.string(),
  title:                z.string(),
  subtitle:             z.string().optional(),
  paragraph:            z.string().optional(),
  moniker:              z.string(),
  accepted_on:          z.number(),
  home:                 ProfileHomePage.optional()
}).strip();
export type ProfileHomePage =
  | ProfileHomeTopic
  | ProfileHomeBundle
;
export const ProfileHomePage = z.discriminatedUnion('kind', [
  ProfileHomeTopic,
  ProfileHomeBundle
]);
export type  ProfileHomeTopic = z.infer<typeof ProfileHomeTopic>;
export const ProfileHomeTopic = z.object({
  kind:                 z.literal('home topic'),
  tkey:                 z.string()
}).strip();
export type  ProfileHomeBundle = z.infer<typeof ProfileHomeBundle>;
export const ProfileHomeBundle = z.object({
  kind:                 z.literal('home bundle'),
  bnum:                 z.number()
}).strip();
TopicItem
                In addition to the values specified by the Userbase Item interface the kind and
                database attributes are added to TopicItem during deserialization.
              
export type  TopicItem = z.infer<typeof TopicItem>;
export const TopicItem = z.object({
  kind:                 z.literal('topicitem'),
  itemId:               z.string(),
  item:                 TopicRecord,
  updatedBy:            z.custom<Attribution>(),
  database:             z.custom<Database>()
}).strip();
export type  TopicRecord = z.infer<typeof TopicRecord>;
export const TopicRecord = z.object({
  kind:                 z.literal('topic'),
  mnum:                 z.number(),
  tnum:                 z.number(),
  tid:                  z.string(),
  dbid:                 z.string()
}).strip();