logo logo
Design: Database: TID-Topic meta

Database TID-Topic
Purpose Hold topic details and track topic members.
Cardinality one TID-Topic database per topic
one TopicDataItem item per topic
one TopicMemberItem per member invited to the topic
Source Code
Items src/ts/dbitems/TID-Topic.ts
Zod Models
item TopicItem - union of TopicDataItem, TopicMemberItem below
item.item one of TopicDataRecord, TopicMemberRecord
itemId 'topicdata'
item: TopicDataRecord
    kind 'topicdata'
    tkey topic key (creator concatenated with transliterated topic number)
    title title of the topic
    description description of topic
    path topic path
    bundles list of TopicBundle in load order
    mtid MTID prefix for member MTID-Activity databases
bnum bundle number
include true if bundle required by topic
itemId member number invited to topic
item: TopicMemberRecord
    kind 'topicmember'
    tnum this topic's topic number
    mnum member number invited to topic (same as itemId)


The TID-Topic database is created when a member creates a new topic.
It holds one TopicDataItem with the details and path for the topic and one TopicMemberItem for each member invited to discuss the topic.

  (see userbase-js/types/index.d.ts)

  export interface Item {              userbase item
    itemId: string                    ╭────────────────────────────────────┐
    item: any ────────────────────┬──▶│ kind: 'topicdata'                  │
    createdBy: Attribution        │   │ tkey: '1A'                         │
    updatedBy?: Attribution       │   │ title: 'Code Samples'              │
    fileId?: string               │   │ mtid: '01HPJFDKDXJCR2Z067PZGHF3YC' │
    fileName?: string             │   │ ...                                │            
    fileSize?: number             │   ╰────────────────────────────────────┘            
    fileUploadedBy?: Attribution  │                                         
    writeAccess?: AccessControl   └──▶╭────────────────────────────────────┐
  }                                   │ kind: 'topicmember'                │
                                      │ tnum: 1                            │
                                      │ mnum: 2                            │
                                      │ mtid: '01HPJFDKDXJCR2Z067PZGHF3YC' │

  TopicRecord represents the specific type of Item.item for an entry
  in the Bundles database - either TopicDataRecord or TopicMemberRecord.


The TID-Topic database holds one TopicDataItem which keeps track of the details for the topic.

The tkey attribute 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 the tkey "3B" indicates the second topic (B) created by member 3.

The mtid attribute holds the prefix of each member's MTID-Activity database of comments for the topic. The mtid is a random ULID not easily guessable or derivable from other information. While a topic's tid is visible to all members of an engengement, the value of a topic's mtid is known only to the topic's members.


The TID-Topic database holds one TopicMemberItem for each member invited to discuss the topic.

The mtid attribute holds the prefix of each member's MTID-Activity database of comments for the topic. The name of a member's MTID-Activity database is derived from the mtid for the topic and the mnum for the member.

Ownership and Access

The creator of the topic is the owner of the TID-Topic database for the topic.

The TID-Topic database shared read-only with the members of the topic.

Zod models

The following Zod models show how the Userbase items are represented in memory.

Note that in addition to the values specified by the Userbase Item interface the kind and database attributes are added during deserialization.

export type TIDTopicItem =
  | TopicDataItem
  | TopicMemberItem
export const TIDTopicItem = z.discriminatedUnion('kind', [


export type  TopicDataItem = z.infer<typeof TopicDataItem>;
export const TopicDataItem = z.object({
  kind:                 z.literal('topicdataitem'),
  itemId:               z.string(),
  item:                 TopicDataRecord,
  updatedBy:            z.custom<Attribution>(),
  database:             z.custom<Database>()
export type  TopicDataRecord = z.infer<typeof TopicDataRecord>;
export const TopicDataRecord = z.object({
  kind:                 z.literal('topicdata'),
  tkey:                 z.string(),
  title:                z.string(),
  description:          z.string(),
  path:                 z.string(),
  bundles:              TopicBundle.array(),
  mtid:                 z.string()
export type  TopicBundle = z.infer<typeof TopicBundle>;
export const TopicBundle = z.object({
  bnum:                 z.number(),
  include:              z.boolean()


export type  TopicMemberItem = z.infer<typeof TopicMemberItem>;
export const TopicMemberItem = z.object({
  kind:                 z.literal('topicmemberitem'),
  itemId:               z.string(),
  item:                 TopicMemberRecord,
  updatedBy:            z.custom<Attribution>(),
  database:             z.custom<Database>()
export type  TopicMemberRecord = z.infer<typeof TopicMemberRecord>;
export const TopicMemberRecord = z.object({
  kind:                 z.literal('topicmember'),
  tnum:                 z.number(),
  mnum:                 z.number()