{
  "id": "original",
  "label": "Current Forum",
  "sources": [
    {
      "fileName": "forum.bosatsu",
      "source": "package Yichus/Examples/Forum\n\n# A messaging forum on the Yichus service framework: profiles (owner\n# scoped), threads with a visibility rule, posts with an edit rule, a\n# moderator roster, and a per-thread reply cap. Written as the demo in\n# docs/forum-demo/. The profiles table is proven OwnerScoped; threads\n# and posts are proven Guarded: every write of them and every use of\n# their rows sits under a branch on `can_see` or `can_edit` applied to\n# the caller, and the access findings name which. The moderator roster\n# stays Public: its bootstrap write (the first caller seats itself) has\n# no row to guard on, and the walkthrough says so.\n\nfrom Yichus/IO import IO, flat_map, pure\nfrom Yichus/Access import Principal, AccessRule, AccessSpec, OwnerScoped, Public, Guarded, keep_visible\nfrom Yichus/Data import Db, Table, table, db_read, db_read_opt, db_write, db_query, db_next_id\nfrom Yichus/Service import (\n  Response, ok, handler, route, service_def, ReadPerm, WritePerm, CreatePerm, QueryPerm\n)\nfrom Yichus/Systems import SystemSpec, SystemBinding, Postgres, Serializable\nfrom Yichus/Organize import FamilySpec, ReadingOrder, ReadingStep\n\nexport (\n  forum_api,\n  access_rules,\n  forum_systems,\n  forum_tables,\n  forum_shape,\n  forum_reading,\n  Profile(),\n  Visibility(),\n  Thread(),\n  Post(),\n  PutProfileRequest(),\n  OpenThreadRequest(),\n  ReadThreadRequest(),\n  ReplyRequest(),\n  EditPostRequest(),\n  GrantModeratorRequest(),\n  Issue(),\n  Outcome(),\n  can_see,\n  can_edit,\n  thread_request_issues,\n  posts_table,\n  put_profile,\n  get_profile,\n  grant_moderator,\n  open_thread,\n  list_threads,\n  read_thread,\n  post_reply,\n  edit_post,\n)\nexposes (Yichus/Access, Yichus/Data, Yichus/IO, Yichus/Organize, Yichus/Service, Yichus/Systems)\n\n# ---------------------------------------------------------------------------\n# Small total combinators shared by every layer below.\n# ---------------------------------------------------------------------------\n\ndef int_lt(a: Int, b: Int) -> Bool:\n  match cmp_Int(a, b):\n    case LT: True\n    case _: False\n\ndef int_gt(a: Int, b: Int) -> Bool:\n  match cmp_Int(a, b):\n    case GT: True\n    case _: False\n\ndef is_blank(s: String) -> Bool:\n  eq_String(s, \"\")\n\ndef contains_String(haystack: String, needle: String) -> Bool:\n  match partition_String(haystack, needle):\n    case Some(_): True\n    case None: False\n\ndef member_String(items: List[String], target: String) -> Bool:\n  loop items:\n    case []: False\n    case [head, *tail]:\n      if eq_String(head, target): True\n      else: member_String(tail, target)\n\ndef join_with(items: List[String], sep: String) -> String:\n  recur items:\n    case []: \"\"\n    case [last]: last\n    case [head, *tail]: concat_String([head, sep, join_with(tail, sep)])\n\n# ---------------------------------------------------------------------------\n# JSON rendering kit: stored strings are validated quote-free, so no\n# escaping pass is needed here.\n# ---------------------------------------------------------------------------\n\ndef quote(s: String) -> String:\n  concat_String([\"\\\"\", s, \"\\\"\"])\n\ndef jstr(key: String, value: String) -> String:\n  concat_String([quote(key), \":\", quote(value)])\n\ndef jint(key: String, value: Int) -> String:\n  concat_String([quote(key), \":\", int_to_String(value)])\n\ndef jraw(key: String, body: String) -> String:\n  concat_String([quote(key), \":\", body])\n\ndef bool_literal(value: Bool) -> String:\n  match value:\n    case True: \"true\"\n    case False: \"false\"\n\ndef jbool(key: String, value: Bool) -> String:\n  jraw(key, bool_literal(value))\n\ndef jobj(fields: List[String]) -> String:\n  concat_String([\"{\", join_with(fields, \",\"), \"}\"])\n\ndef jarr(items: List[String]) -> String:\n  concat_String([\"[\", join_with(items, \",\"), \"]\"])\n\ndef jarr_of_str(items: List[String]) -> String:\n  jarr(map_List(items, quote))\n\n# ---------------------------------------------------------------------------\n# Validation kit: issues, checks, the Outcome accumulator.\n# ---------------------------------------------------------------------------\n\nstruct Issue(field: String, code: String, hint: String)\n\nenum Outcome[a]:\n  Failure(issues: List[Issue])\n  Success(value: a)\n\ndef flag_if(cond: Bool, field: String, code: String, hint: String) -> List[Issue]:\n  if cond: [Issue(field, code, hint)]\n  else: []\n\ndef merge_issues(batches: List[List[Issue]]) -> List[Issue]:\n  flat_map_List(batches, batch -> batch)\n\ndef check_blank(field: String, value: String) -> List[Issue]:\n  flag_if(is_blank(value), field, \"required\", \"value must not be empty\")\n\ndef check_clean(field: String, value: String) -> List[Issue]:\n  flag_if(contains_String(value, \"\\\"\"), field, \"forbidden_quote\",\n    \"double quotes are not allowed in stored text\")\n\ndef check_max_len(field: String, value: String, limit: Int) -> List[Issue]:\n  over = int_gt(length_String(value), limit)\n  merge_issues([\n    flag_if(over, field, \"too_long\",\n      concat_String([\"at most \", int_to_String(limit), \" characters\"])),\n    check_clean(field, value),\n  ])\n\ndef check_text(field: String, value: String, limit: Int) -> List[Issue]:\n  merge_issues([\n    check_blank(field, value),\n    check_max_len(field, value, limit),\n  ])\n\ndef outcome_of[a](issues: List[Issue], value: a) -> Outcome[a]:\n  match issues:\n    case []: Success(value)\n    case _: Failure(issues)\n\n# ---------------------------------------------------------------------------\n# Response envelopes shared by every handler. `forbid` and `not_found`\n# are the runtime rules the access analyzer cannot prove: they carry no\n# row data, so a caller the rule turns away learns only that it was.\n# ---------------------------------------------------------------------------\n\ndef render_issue(issue: Issue) -> String:\n  Issue(field, code, hint) = issue\n  jobj([jstr(\"field\", field), jstr(\"code\", code), jstr(\"hint\", hint)])\n\ndef respond(view: String, fields: List[String]) -> Response:\n  ok(jobj([jstr(\"view\", view), *fields]))\n\ndef reject(issues: List[Issue]) -> Response:\n  Response(422, jobj([\n    jstr(\"view\", \"rejected\"),\n    jint(\"issue_count\", length_List(issues)),\n    jraw(\"issues\", jarr(map_List(issues, render_issue))),\n  ]))\n\ndef forbid(rule: String, message: String) -> Response:\n  Response(403, jobj([jstr(\"view\", \"forbidden\"), jstr(\"rule\", rule), jstr(\"message\", message)]))\n\ndef not_found(what: String) -> Response:\n  Response(404, jobj([jstr(\"view\", \"not_found\"), jstr(\"what\", what)]))\n\n# ---------------------------------------------------------------------------\n# Domain records.\n# ---------------------------------------------------------------------------\n\nstruct Profile(user_id: String, display_name: String)\n\n# Who may read a thread: everyone, or its author, its members and the\n# moderators.\nenum Visibility:\n  Open\n  Members\n\nstruct Thread(\n  id: String,\n  title: String,\n  author: String,\n  visibility: Visibility,\n  members: List[String],\n  reply_cap: Int\n)\n\nstruct Post(id: String, thread_id: String, author: String, body: String, edited: Bool)\n\ndef render_visibility(v: Visibility) -> String:\n  match v:\n    case Open: \"open\"\n    case Members: \"members\"\n\ndef render_profile(profile: Profile) -> String:\n  Profile(user_id, display_name) = profile\n  jobj([jstr(\"user_id\", user_id), jstr(\"display_name\", display_name)])\n\ndef render_thread(thread: Thread) -> String:\n  Thread(id, title, author, visibility, members, reply_cap) = thread\n  jobj([\n    jstr(\"id\", id),\n    jstr(\"title\", title),\n    jstr(\"author\", author),\n    jstr(\"visibility\", render_visibility(visibility)),\n    jraw(\"members\", jarr_of_str(members)),\n    jint(\"reply_cap\", reply_cap),\n  ])\n\ndef render_post(post: Post) -> String:\n  Post(id, thread_id, author, body, edited) = post\n  jobj([\n    jstr(\"id\", id),\n    jstr(\"thread_id\", thread_id),\n    jstr(\"author\", author),\n    jstr(\"body\", body),\n    jbool(\"edited\", edited),\n  ])\n\n# ---------------------------------------------------------------------------\n# The rules. Pure, so `why` can show them and a law can pin them.\n# ---------------------------------------------------------------------------\n\ndef is_moderator(roster: List[String], uid: String) -> Bool:\n  member_String(roster, uid)\n\n# The visibility rule: an Open thread is readable by every caller; a\n# Members thread by its author, its members and the moderators.\ndef can_see(uid: String, roster: List[String], thread: Thread) -> Bool:\n  Thread(_, _, author, visibility, members, _) = thread\n  match visibility:\n    case Open: True\n    case Members:\n      or(eq_String(author, uid), or(member_String(members, uid), is_moderator(roster, uid)))\n\n# The edit rule: a post is edited by its author or by a moderator.\ndef can_edit(uid: String, roster: List[String], post: Post) -> Bool:\n  Post(_, _, author, _, _) = post\n  or(eq_String(author, uid), is_moderator(roster, uid))\n\n# The reply cap: a thread admits a reply while its replies number fewer\n# than its cap.\ndef has_room(thread: Thread, replies: List[Post]) -> Bool:\n  Thread(_, _, _, _, _, reply_cap) = thread\n  int_lt(length_List(replies), reply_cap)\n\ndef post_id_is(post: Post, target: String) -> Bool:\n  Post(id, _, _, _, _) = post\n  eq_String(id, target)\n\ndef replace_post(posts: List[Post], edited: Post) -> List[Post]:\n  Post(target, _, _, _, _) = edited\n  map_List(posts, post -> (\n    if post_id_is(post, target): edited\n    else: post))\n\ndef find_post(posts: List[Post], target: String) -> Option[Post]:\n  loop posts:\n    case []: None\n    case [head, *tail]:\n      if post_id_is(head, target): Some(head)\n      else: find_post(tail, target)\n\n# ---------------------------------------------------------------------------\n# Storage layout. `profiles` is one record per caller keyed by\n# Principal.user_id (proven OwnerScoped). `threads` is one record per\n# thread id, `posts` the list of a thread's posts under the thread id;\n# both are Guarded: a write is a create (keyed by the table's own fresh\n# id) or sits under `can_see` / `can_edit` applied to the caller, and a\n# row read reaches nothing but such a branch, a guard, a match, or\n# `keep_visible`. The moderator roster is one Public row. Record tables\n# are read with `db_read_opt`, so a missing thread is `None`, never a\n# wrong-typed record.\n# ---------------------------------------------------------------------------\n\naccess_rules = AccessSpec([\n  AccessRule(\"profiles\", OwnerScoped),\n  AccessRule(\"threads\", Guarded([\"can_see\"])),\n  AccessRule(\"posts\", Guarded([\"can_see\", \"can_edit\"])),\n  AccessRule(\"moderators\", Public),\n])\n\n# The eventual backing store, declared for the flow lens: a claim about\n# the deployment, not a connection (the engine's store is configured at\n# boot; see docs/forum-demo/).\nforum_systems = SystemSpec([\n  SystemBinding(\"threads\", Postgres(\"forum\", Serializable)),\n  SystemBinding(\"posts\", Postgres(\"forum\", Serializable)),\n  SystemBinding(\"profiles\", Postgres(\"forum\", Serializable)),\n  SystemBinding(\"moderators\", Postgres(\"forum\", Serializable)),\n])\n\n# The shape the forum declares about itself, checked by the organize\n# pages: the four tables are one family and the eight handlers are\n# written the same way (the conventions page names any member that\n# diverges and any inferred member the declaration omits), and a reader learns the blocks in this\n# order (the stack page names any step listed before a block it is\n# built from). Every caption is authored, never measured.\nforum_tables = FamilySpec(\"tables\", [\n  \"profiles_table\", \"threads_table\", \"posts_table\", \"moderators_table\",\n])\n\nforum_shape = FamilySpec(\"handlers\", [\n  \"get_profile\", \"put_profile\", \"grant_moderator\", \"open_thread\",\n  \"list_threads\", \"read_thread\", \"post_reply\", \"edit_post\",\n])\n\nforum_reading = ReadingOrder([\n  ReadingStep(\"quote\", \"wraps a string in JSON quotes; every JSON line below uses it\"),\n  ReadingStep(\"join_with\", \"joins strings with a separator; the JSON arrays and objects are built on it\"),\n  ReadingStep(\"jraw\", \"one JSON field whose value is already JSON text\"),\n  ReadingStep(\"jstr\", \"one JSON field holding a quoted string\"),\n  ReadingStep(\"jobj\", \"a JSON object from a list of fields\"),\n  ReadingStep(\"jarr\", \"a JSON array from a list of already-rendered items\"),\n  ReadingStep(\"threads_table\", \"the threads table handle, one Thread per id\"),\n  ReadingStep(\"posts_table\", \"the posts table handle, a list of Post per thread id\"),\n  ReadingStep(\"moderators_table\", \"the moderator roster table, one list of user ids\"),\n  ReadingStep(\"profiles_table\", \"the profiles table handle, one Profile per user id\"),\n  ReadingStep(\"is_moderator\", \"whether a user id is on the roster\"),\n  ReadingStep(\"can_see\", \"the visibility rule: who may read a thread, by its visibility and members\"),\n  ReadingStep(\"can_edit\", \"the edit rule: the author or a moderator\"),\n  ReadingStep(\"respond\", \"a 200 response with a named view and its JSON fields\"),\n  ReadingStep(\"forbid\", \"a 403 response naming the rule that refused\"),\n  ReadingStep(\"not_found\", \"a 404 response naming what was missing\"),\n  ReadingStep(\"flag_if\", \"one validation issue when a condition holds\"),\n  ReadingStep(\"check_text\", \"the text validation every request body and title goes through\"),\n  ReadingStep(\"reject\", \"a 400 response carrying the validation issues\"),\n  ReadingStep(\"render_thread\", \"a thread as JSON\"),\n  ReadingStep(\"render_post\", \"a post as JSON\"),\n  ReadingStep(\"has_room\", \"whether a thread is under its reply cap\"),\n  ReadingStep(\"get_profile\", \"the caller reads their own profile\"),\n  ReadingStep(\"put_profile\", \"the caller writes their own profile after validation\"),\n  ReadingStep(\"grant_moderator\", \"a moderator adds a user to the roster; the first caller seats itself\"),\n  ReadingStep(\"list_threads\", \"the threads the caller may see\"),\n  ReadingStep(\"read_thread\", \"one thread and its posts, if the caller may see it\"),\n  ReadingStep(\"post_reply\", \"a reply under the visibility rule and the reply cap\"),\n  ReadingStep(\"edit_post\", \"an edit under the visibility rule and the edit rule\"),\n  ReadingStep(\"thread_request_issues\", \"the validation issues of an open-thread request\"),\n  ReadingStep(\"parse_thread\", \"a validated open-thread request as a Thread, or its issues\"),\n  ReadingStep(\"open_thread\", \"a new thread from a validated request\"),\n  ReadingStep(\"forum_api\", \"the service: eight routes, each a handler with its permissions\"),\n])\n\ndef profiles_table(db: Db) -> Table[Profile]:\n  table(db, \"profiles\")\n\ndef threads_table(db: Db) -> Table[Thread]:\n  table(db, \"threads\")\n\ndef posts_table(db: Db) -> Table[List[Post]]:\n  table(db, \"posts\")\n\ndef moderators_table(db: Db) -> Table[List[String]]:\n  table(db, \"moderators\")\n\nroster_key = \"roster\"\n\n# ---------------------------------------------------------------------------\n# Requests.\n# ---------------------------------------------------------------------------\n\nstruct PutProfileRequest(display_name: String)\nstruct OpenThreadRequest(title: String, members_only: Bool, members: List[String], reply_cap: Int)\nstruct ReadThreadRequest(thread_id: String)\nstruct ReplyRequest(thread_id: String, body: String)\nstruct EditPostRequest(thread_id: String, post_id: String, body: String)\nstruct GrantModeratorRequest(user_id: String)\n\ndef visibility_of(members_only: Bool) -> Visibility:\n  match members_only:\n    case True: Members\n    case False: Open\n\n# The validation of a thread request, on its own so a declared model\n# (forum.spec.bosatsu) can share it with the handler.\ndef thread_request_issues(req: OpenThreadRequest) -> List[Issue]:\n  OpenThreadRequest(title, _, members, reply_cap) = req\n  merge_issues([\n    check_text(\"title\", title, 80),\n    flag_if(int_lt(reply_cap, 0), \"reply_cap\", \"negative\", \"a cap is zero or more replies\"),\n    flat_map_List(members, member -> check_text(\"members\", member, 40)),\n  ])\n\ndef parse_thread(uid: String, fresh_id: String, req: OpenThreadRequest) -> Outcome[Thread]:\n  OpenThreadRequest(title, members_only, members, reply_cap) = req\n  outcome_of(thread_request_issues(req),\n    Thread(fresh_id, title, uid, visibility_of(members_only), members, reply_cap))\n\n# ---------------------------------------------------------------------------\n# Handlers: (Db, Principal, request) -> IO[Response]. The engine injects\n# Db and Principal; nothing here constructs a Principal.\n# ---------------------------------------------------------------------------\n\ndef put_profile(db: Db, p: Principal, req: PutProfileRequest) -> IO[Response]:\n  Principal(uid, _) = p\n  PutProfileRequest(display_name) = req\n  match check_text(\"display_name\", display_name, 40):\n    case []:\n      stored <- flat_map(db_write(profiles_table(db), uid, Profile(uid, display_name)))\n      pure(respond(\"profile\", [jraw(\"profiles\", jarr([render_profile(stored)]))]))\n    case issues: pure(reject(issues))\n\ndef get_profile(db: Db, p: Principal) -> IO[Response]:\n  Principal(uid, _) = p\n  row <- flat_map(db_read_opt(profiles_table(db), uid))\n  profiles = match row:\n    case None: []\n    case Some(profile): [profile]\n  pure(respond(\"profile\", [jraw(\"profiles\", jarr(map_List(profiles, render_profile)))]))\n\n# The first caller of an empty roster seats itself; after that only a\n# moderator grants.\ndef grant_moderator(db: Db, p: Principal, req: GrantModeratorRequest) -> IO[Response]:\n  Principal(uid, _) = p\n  GrantModeratorRequest(target) = req\n  roster <- flat_map(db_read(moderators_table(db), roster_key))\n  match roster:\n    case []:\n      seated <- flat_map(db_write(moderators_table(db), roster_key, [uid]))\n      pure(respond(\"moderators\", [jraw(\"roster\", jarr_of_str(seated))]))\n    case _:\n      if is_moderator(roster, uid):\n        grown = (\n          if member_String(roster, target): roster\n          else: [target, *roster])\n        stored <- flat_map(db_write(moderators_table(db), roster_key, grown))\n        pure(respond(\"moderators\", [jraw(\"roster\", jarr_of_str(stored))]))\n      else: pure(forbid(\"only a moderator grants moderator\", \"Only a moderator can make someone a moderator.\"))\n\ndef open_thread(db: Db, p: Principal, req: OpenThreadRequest) -> IO[Response]:\n  Principal(uid, _) = p\n  fresh_id <- flat_map(db_next_id(threads_table(db)))\n  match parse_thread(uid, fresh_id, req):\n    case Failure(issues): pure(reject(issues))\n    case Success(thread):\n      stored <- flat_map(db_write(threads_table(db), fresh_id, thread))\n      pure(respond(\"thread\", [jraw(\"threads\", jarr([render_thread(stored)]))]))\n\ndef list_threads(db: Db, p: Principal) -> IO[Response]:\n  Principal(uid, _) = p\n  roster <- flat_map(db_read(moderators_table(db), roster_key))\n  rows <- flat_map(db_query(threads_table(db)))\n  visible = keep_visible(rows, thread -> can_see(uid, roster, thread))\n  pure(respond(\"threads\", [\n    jint(\"count\", length_List(visible)),\n    jraw(\"threads\", jarr(map_List(visible, render_thread))),\n  ]))\n\ndef read_thread(db: Db, p: Principal, req: ReadThreadRequest) -> IO[Response]:\n  Principal(uid, _) = p\n  ReadThreadRequest(thread_id) = req\n  roster <- flat_map(db_read(moderators_table(db), roster_key))\n  row <- flat_map(db_read_opt(threads_table(db), thread_id))\n  match row:\n    case None: pure(not_found(\"thread\"))\n    case Some(thread):\n      if can_see(uid, roster, thread):\n        posts <- flat_map(db_read(posts_table(db), thread_id))\n        pure(respond(\"thread\", [\n          jraw(\"thread\", render_thread(thread)),\n          jint(\"reply_count\", length_List(posts)),\n          jraw(\"posts\", jarr(map_List(posts, render_post))),\n        ]))\n      else: pure(forbid(\"members only\", \"This thread is for its members only.\"))\n\ndef post_reply(db: Db, p: Principal, req: ReplyRequest) -> IO[Response]:\n  Principal(uid, _) = p\n  ReplyRequest(thread_id, body) = req\n  match check_text(\"body\", body, 500):\n    case [issue, *more]: pure(reject([issue, *more]))\n    case []:\n      roster <- flat_map(db_read(moderators_table(db), roster_key))\n      row <- flat_map(db_read_opt(threads_table(db), thread_id))\n      match row:\n        case None: pure(not_found(\"thread\"))\n        case Some(thread):\n          if can_see(uid, roster, thread):\n            posts <- flat_map(db_read(posts_table(db), thread_id))\n            if has_room(thread, posts):\n              fresh_id <- flat_map(db_next_id(posts_table(db)))\n              stored <- flat_map(db_write(posts_table(db), thread_id,\n                [*posts, Post(fresh_id, thread_id, uid, body, False)]))\n              pure(respond(\"thread\", [\n                jraw(\"thread\", render_thread(thread)),\n                jint(\"reply_count\", length_List(stored)),\n                jraw(\"posts\", jarr(map_List(stored, render_post))),\n              ]))\n            else: pure(reject([Issue(\"thread_id\", \"thread_full\", \"the thread has reached its reply cap\")]))\n          else: pure(forbid(\"members only\", \"This thread is for its members only.\"))\n\ndef edit_post(db: Db, p: Principal, req: EditPostRequest) -> IO[Response]:\n  Principal(uid, _) = p\n  EditPostRequest(thread_id, post_id, body) = req\n  match check_text(\"body\", body, 500):\n    case [issue, *more]: pure(reject([issue, *more]))\n    case []:\n      roster <- flat_map(db_read(moderators_table(db), roster_key))\n      row <- flat_map(db_read_opt(threads_table(db), thread_id))\n      match row:\n        case None: pure(not_found(\"thread\"))\n        case Some(thread):\n          if can_see(uid, roster, thread):\n            posts <- flat_map(db_read(posts_table(db), thread_id))\n            match find_post(posts, post_id):\n              case None: pure(not_found(\"post\"))\n              case Some(post):\n                if can_edit(uid, roster, post):\n                  Post(_, _, author, _, _) = post\n                  stored <- flat_map(db_write(posts_table(db), thread_id,\n                    replace_post(posts, Post(post_id, thread_id, author, body, True))))\n                  pure(respond(\"thread\", [\n                    jraw(\"thread\", render_thread(thread)),\n                    jint(\"reply_count\", length_List(stored)),\n                    jraw(\"posts\", jarr(map_List(stored, render_post))),\n                  ]))\n                else: pure(forbid(\"author or moderator\", \"Only the post's author or a moderator can edit it.\"))\n          else: pure(forbid(\"members only\", \"This thread is for its members only.\"))\n\nforum_api = service_def(\n  \"forum\",\n  [\n    route(\"/profile\", handler(\"get_profile\", get_profile), [ReadPerm(\"profiles\")]),\n    route(\"/profile/put\", handler(\"put_profile\", put_profile), [WritePerm(\"profiles\")]),\n    route(\"/moderators/grant\", handler(\"grant_moderator\", grant_moderator),\n      [ReadPerm(\"moderators\"), WritePerm(\"moderators\")]),\n    route(\"/threads/open\", handler(\"open_thread\", open_thread),\n      [CreatePerm(\"threads\"), WritePerm(\"threads\")]),\n    route(\"/threads\", handler(\"list_threads\", list_threads),\n      [ReadPerm(\"moderators\"), QueryPerm(\"threads\")]),\n    route(\"/threads/read\", handler(\"read_thread\", read_thread),\n      [ReadPerm(\"moderators\"), ReadPerm(\"threads\"), ReadPerm(\"posts\")]),\n    route(\"/posts/reply\", handler(\"post_reply\", post_reply),\n      [ReadPerm(\"moderators\"), ReadPerm(\"threads\"), ReadPerm(\"posts\"), CreatePerm(\"posts\"), WritePerm(\"posts\")]),\n    route(\"/posts/edit\", handler(\"edit_post\", edit_post),\n      [ReadPerm(\"moderators\"), ReadPerm(\"threads\"), ReadPerm(\"posts\"), WritePerm(\"posts\")]),\n  ]\n)\n"
    }
  ],
  "view": {
    "schemaVersion": "implementation-view-1",
    "question": "Where do the thread handlers assemble their response?",
    "pins": [
      "Yichus/Examples/Forum::read_thread",
      "Yichus/Examples/Forum::post_reply",
      "Yichus/Examples/Forum::edit_post"
    ],
    "groups": [
      {
        "id": "handlers",
        "label": "Request handlers",
        "members": [
          "Yichus/Examples/Forum::put_profile",
          "Yichus/Examples/Forum::get_profile",
          "Yichus/Examples/Forum::grant_moderator",
          "Yichus/Examples/Forum::open_thread",
          "Yichus/Examples/Forum::list_threads",
          "Yichus/Examples/Forum::read_thread",
          "Yichus/Examples/Forum::post_reply",
          "Yichus/Examples/Forum::edit_post"
        ]
      },
      {
        "id": "decisions",
        "label": "Access & validation",
        "members": []
      },
      {
        "id": "access",
        "label": "Access decisions",
        "members": [
          "Yichus/Examples/Forum::is_moderator",
          "Yichus/Examples/Forum::can_see",
          "Yichus/Examples/Forum::can_edit",
          "Yichus/Examples/Forum::has_room"
        ],
        "parent": "decisions"
      },
      {
        "id": "validation",
        "label": "Request validation",
        "members": [
          "Yichus/Examples/Forum::check_text",
          "Yichus/Examples/Forum::check_blank",
          "Yichus/Examples/Forum::check_clean",
          "Yichus/Examples/Forum::check_max_len",
          "Yichus/Examples/Forum::flag_if",
          "Yichus/Examples/Forum::merge_issues",
          "Yichus/Examples/Forum::outcome_of",
          "Yichus/Examples/Forum::thread_request_issues",
          "Yichus/Examples/Forum::parse_thread",
          "Yichus/Examples/Forum::visibility_of"
        ],
        "parent": "decisions"
      },
      {
        "id": "representation",
        "label": "Representations",
        "members": []
      },
      {
        "id": "response",
        "label": "Response envelopes",
        "members": [
          "Yichus/Examples/Forum::respond",
          "Yichus/Examples/Forum::reject",
          "Yichus/Examples/Forum::forbid",
          "Yichus/Examples/Forum::not_found"
        ],
        "parent": "representation"
      },
      {
        "id": "records",
        "label": "Record rendering",
        "members": [
          "Yichus/Examples/Forum::render_issue",
          "Yichus/Examples/Forum::render_visibility",
          "Yichus/Examples/Forum::render_profile",
          "Yichus/Examples/Forum::render_thread",
          "Yichus/Examples/Forum::render_post"
        ],
        "parent": "representation"
      },
      {
        "id": "json",
        "label": "JSON building blocks",
        "members": [
          "Yichus/Examples/Forum::quote",
          "Yichus/Examples/Forum::jstr",
          "Yichus/Examples/Forum::jint",
          "Yichus/Examples/Forum::jraw",
          "Yichus/Examples/Forum::bool_literal",
          "Yichus/Examples/Forum::jbool",
          "Yichus/Examples/Forum::jobj",
          "Yichus/Examples/Forum::jarr",
          "Yichus/Examples/Forum::jarr_of_str"
        ],
        "parent": "representation"
      },
      {
        "id": "storage",
        "label": "Table handles",
        "members": [
          "Yichus/Examples/Forum::profiles_table",
          "Yichus/Examples/Forum::threads_table",
          "Yichus/Examples/Forum::posts_table",
          "Yichus/Examples/Forum::moderators_table",
          "Yichus/Examples/Forum::roster_key"
        ]
      },
      {
        "id": "collections",
        "label": "Collection operations",
        "members": [
          "Yichus/Examples/Forum::post_id_is",
          "Yichus/Examples/Forum::replace_post",
          "Yichus/Examples/Forum::find_post",
          "Yichus/Examples/Forum::member_String",
          "Yichus/Examples/Forum::join_with",
          "Yichus/Examples/Forum::int_lt",
          "Yichus/Examples/Forum::int_gt",
          "Yichus/Examples/Forum::is_blank",
          "Yichus/Examples/Forum::contains_String"
        ]
      },
      {
        "id": "configuration",
        "label": "Service declarations",
        "members": [
          "Yichus/Examples/Forum::forum_api",
          "Yichus/Examples/Forum::access_rules",
          "Yichus/Examples/Forum::forum_systems",
          "Yichus/Examples/Forum::forum_tables",
          "Yichus/Examples/Forum::forum_shape",
          "Yichus/Examples/Forum::forum_reading"
        ]
      }
    ],
    "roles": [
      {
        "id": "representation",
        "label": "Representation",
        "references": [
          "Yichus/Examples/Forum::respond",
          "Yichus/Examples/Forum::render_thread",
          "Yichus/Examples/Forum::render_post",
          "Yichus/Examples/Forum::jraw",
          "Yichus/Examples/Forum::jint",
          "Yichus/Examples/Forum::jarr"
        ]
      },
      {
        "id": "decisions",
        "label": "Decisions",
        "references": [
          "Yichus/Examples/Forum::can_see",
          "Yichus/Examples/Forum::can_edit",
          "Yichus/Examples/Forum::has_room",
          "Yichus/Examples/Forum::check_text"
        ]
      },
      {
        "id": "storage",
        "label": "Table handles",
        "references": [
          "Yichus/Examples/Forum::threads_table",
          "Yichus/Examples/Forum::posts_table",
          "Yichus/Examples/Forum::moderators_table"
        ]
      }
    ]
  },
  "artifact": {
    "schemaVersion": "implementation-comparison-1",
    "snapshot": "7a3d60b9e56e1be62f0c6f0492715a71ffdc452a1432628628781b24f5876c96",
    "question": "Where do the thread handlers assemble their response?",
    "order": [],
    "pins": [
      "Yichus/Examples/Forum::read_thread",
      "Yichus/Examples/Forum::post_reply",
      "Yichus/Examples/Forum::edit_post"
    ],
    "nodes": [
      {
        "id": "Yichus/Examples/Forum::access_rules",
        "name": "access_rules",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Access::AccessSpec",
        "signatureId": "Yichus/Access::AccessSpec",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 10248,
          "end": 10442,
          "label": "forum:303:16",
          "source": "AccessSpec([\n  AccessRule(\"profiles\", OwnerScoped),\n  AccessRule(\"threads\", Guarded([\"can_see\"])),\n  AccessRule(\"posts\", Guarded([\"can_see\", \"can_edit\"])),\n  AccessRule(\"moderators\", Public),\n])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::bool_literal",
        "name": "bool_literal",
        "package": "Yichus/Examples/Forum",
        "signature": "Bool -> String",
        "signatureId": "Bosatsu/Predef::Bool -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3400,
          "end": 3458,
          "label": "forum:109:3",
          "source": "match value:\n    case True: \"true\"\n    case False: \"false\""
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::can_edit",
        "name": "can_edit",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, List[String], Post) -> Bool",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::List[Bosatsu/Predef::String], Yichus/Examples/Forum::Post) -> Bosatsu/Predef::Bool",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 8675,
          "end": 8762,
          "label": "forum:265:3",
          "source": "Post(_, _, author, _, _) = post\n  or(eq_String(author, uid), is_moderator(roster, uid))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::can_see",
        "name": "can_see",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, List[String], Thread) -> Bool",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::List[Bosatsu/Predef::String], Yichus/Examples/Forum::Thread) -> Bosatsu/Predef::Bool",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 8331,
          "end": 8535,
          "label": "forum:257:3",
          "source": "Thread(_, _, author, visibility, members, _) = thread\n  match visibility:\n    case Open: True\n    case Members:\n      or(eq_String(author, uid), or(member_String(members, uid), is_moderator(roster, uid)))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::check_blank",
        "name": "check_blank",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String) -> List[Issue]",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String) -> Bosatsu/Predef::List[Yichus/Examples/Forum::Issue]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 4451,
          "end": 4521,
          "label": "forum:143:3",
          "source": "flag_if(is_blank(value), field, \"required\", \"value must not be empty\")"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::check_clean",
        "name": "check_clean",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String) -> List[Issue]",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String) -> Bosatsu/Predef::List[Yichus/Examples/Forum::Issue]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 4587,
          "end": 4702,
          "label": "forum:146:3",
          "source": "flag_if(contains_String(value, \"\\\"\"), field, \"forbidden_quote\",\n    \"double quotes are not allowed in stored text\")"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::check_max_len",
        "name": "check_max_len",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String, Int) -> List[Issue]",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String, Bosatsu/Predef::Int) -> Bosatsu/Predef::List[Yichus/Examples/Forum::Issue]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 4782,
          "end": 4987,
          "label": "forum:150:3",
          "source": "over = int_gt(length_String(value), limit)\n  merge_issues([\n    flag_if(over, field, \"too_long\",\n      concat_String([\"at most \", int_to_String(limit), \" characters\"])),\n    check_clean(field, value),\n  ])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::check_text",
        "name": "check_text",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String, Int) -> List[Issue]",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String, Bosatsu/Predef::Int) -> Bosatsu/Predef::List[Yichus/Examples/Forum::Issue]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 5064,
          "end": 5154,
          "label": "forum:158:3",
          "source": "merge_issues([\n    check_blank(field, value),\n    check_max_len(field, value, limit),\n  ])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::contains_String",
        "name": "contains_String",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String) -> Bool",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String) -> Bosatsu/Predef::Bool",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 2269,
          "end": 2354,
          "label": "forum:74:3",
          "source": "match partition_String(haystack, needle):\n    case Some(_): True\n    case None: False"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::edit_post",
        "name": "edit_post",
        "package": "Yichus/Examples/Forum",
        "signature": "(Yichus/Data::Db, Yichus/Access::Principal, EditPostRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "signatureId": "(Yichus/Data::Db, Yichus/Access::Principal, Yichus/Examples/Forum::EditPostRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 20765,
          "end": 22114,
          "label": "forum:519:3",
          "source": "Principal(uid, _) = p\n  EditPostRequest(thread_id, post_id, body) = req\n  match check_text(\"body\", body, 500):\n    case [issue, *more]: pure(reject([issue, *more]))\n    case []:\n      roster <- flat_map(db_read(moderators_table(db), roster_key))\n      row <- flat_map(db_read_opt(threads_table(db), thread_id))\n      match row:\n        case None: pure(not_found(\"thread\"))\n        case Some(thread):\n          if can_see(uid, roster, thread):\n            posts <- flat_map(db_read(posts_table(db), thread_id))\n            match find_post(posts, post_id):\n              case None: pure(not_found(\"post\"))\n              case Some(post):\n                if can_edit(uid, roster, post):\n                  Post(_, _, author, _, _) = post\n                  stored <- flat_map(db_write(posts_table(db), thread_id,\n                    replace_post(posts, Post(post_id, thread_id, author, body, True))))\n                  pure(respond(\"thread\", [\n                    jraw(\"thread\", render_thread(thread)),\n                    jint(\"reply_count\", length_List(stored)),\n                    jraw(\"posts\", jarr(map_List(stored, render_post))),\n                  ]))\n                else: pure(forbid(\"author or moderator\", \"Only the post's author or a moderator can edit it.\"))\n          else: pure(forbid(\"members only\", \"This thread is for its members only.\"))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::find_post",
        "name": "find_post",
        "package": "Yichus/Examples/Forum",
        "signature": "(List[Post], String) -> Option[Post]",
        "signatureId": "(Bosatsu/Predef::List[Yichus/Examples/Forum::Post], Bosatsu/Predef::String) -> Bosatsu/Predef::Option[Yichus/Examples/Forum::Post]",
        "exported": false,
        "location": null,
        "repetition": [
          {
            "kind": "compiled-loop",
            "location": null
          }
        ]
      },
      {
        "id": "Yichus/Examples/Forum::flag_if",
        "name": "flag_if",
        "package": "Yichus/Examples/Forum",
        "signature": "(Bool, String, String, String) -> List[Issue]",
        "signatureId": "(Bosatsu/Predef::Bool, Bosatsu/Predef::String, Bosatsu/Predef::String, Bosatsu/Predef::String) -> Bosatsu/Predef::List[Yichus/Examples/Forum::Issue]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 4236,
          "end": 4282,
          "label": "forum:136:3",
          "source": "if cond: [Issue(field, code, hint)]\n  else: []"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::forbid",
        "name": "forbid",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String) -> Yichus/Service::Response",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String) -> Yichus/Service::Response",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 6181,
          "end": 6275,
          "label": "forum:189:3",
          "source": "Response(403, jobj([jstr(\"view\", \"forbidden\"), jstr(\"rule\", rule), jstr(\"message\", message)]))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::forum_api",
        "name": "forum_api",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Service::ServiceDef",
        "signatureId": "Yichus/Service::ServiceDef",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 22128,
          "end": 23165,
          "label": "forum:546:13",
          "source": "service_def(\n  \"forum\",\n  [\n    route(\"/profile\", handler(\"get_profile\", get_profile), [ReadPerm(\"profiles\")]),\n    route(\"/profile/put\", handler(\"put_profile\", put_profile), [WritePerm(\"profiles\")]),\n    route(\"/moderators/grant\", handler(\"grant_moderator\", grant_moderator),\n      [ReadPerm(\"moderators\"), WritePerm(\"moderators\")]),\n    route(\"/threads/open\", handler(\"open_thread\", open_thread),\n      [CreatePerm(\"threads\"), WritePerm(\"threads\")]),\n    route(\"/threads\", handler(\"list_threads\", list_threads),\n      [ReadPerm(\"moderators\"), QueryPerm(\"threads\")]),\n    route(\"/threads/read\", handler(\"read_thread\", read_thread),\n      [ReadPerm(\"moderators\"), ReadPerm(\"threads\"), ReadPerm(\"posts\")]),\n    route(\"/posts/reply\", handler(\"post_reply\", post_reply),\n      [ReadPerm(\"moderators\"), ReadPerm(\"threads\"), ReadPerm(\"posts\"), CreatePerm(\"posts\"), WritePerm(\"posts\")]),\n    route(\"/posts/edit\", handler(\"edit_post\", edit_post),\n      [ReadPerm(\"moderators\"), ReadPerm(\"threads\"), ReadPerm(\"posts\"), WritePerm(\"posts\")]),\n  ]\n)"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::forum_reading",
        "name": "forum_reading",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Organize::ReadingOrder",
        "signatureId": "Yichus/Organize::ReadingOrder",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 11623,
          "end": 14255,
          "label": "forum:335:17",
          "source": "ReadingOrder([\n  ReadingStep(\"quote\", \"wraps a string in JSON quotes; every JSON line below uses it\"),\n  ReadingStep(\"join_with\", \"joins strings with a separator; the JSON arrays and objects are built on it\"),\n  ReadingStep(\"jraw\", \"one JSON field whose value is already JSON text\"),\n  ReadingStep(\"jstr\", \"one JSON field holding a quoted string\"),\n  ReadingStep(\"jobj\", \"a JSON object from a list of fields\"),\n  ReadingStep(\"jarr\", \"a JSON array from a list of already-rendered items\"),\n  ReadingStep(\"threads_table\", \"the threads table handle, one Thread per id\"),\n  ReadingStep(\"posts_table\", \"the posts table handle, a list of Post per thread id\"),\n  ReadingStep(\"moderators_table\", \"the moderator roster table, one list of user ids\"),\n  ReadingStep(\"profiles_table\", \"the profiles table handle, one Profile per user id\"),\n  ReadingStep(\"is_moderator\", \"whether a user id is on the roster\"),\n  ReadingStep(\"can_see\", \"the visibility rule: who may read a thread, by its visibility and members\"),\n  ReadingStep(\"can_edit\", \"the edit rule: the author or a moderator\"),\n  ReadingStep(\"respond\", \"a 200 response with a named view and its JSON fields\"),\n  ReadingStep(\"forbid\", \"a 403 response naming the rule that refused\"),\n  ReadingStep(\"not_found\", \"a 404 response naming what was missing\"),\n  ReadingStep(\"flag_if\", \"one validation issue when a condition holds\"),\n  ReadingStep(\"check_text\", \"the text validation every request body and title goes through\"),\n  ReadingStep(\"reject\", \"a 400 response carrying the validation issues\"),\n  ReadingStep(\"render_thread\", \"a thread as JSON\"),\n  ReadingStep(\"render_post\", \"a post as JSON\"),\n  ReadingStep(\"has_room\", \"whether a thread is under its reply cap\"),\n  ReadingStep(\"get_profile\", \"the caller reads their own profile\"),\n  ReadingStep(\"put_profile\", \"the caller writes their own profile after validation\"),\n  ReadingStep(\"grant_moderator\", \"a moderator adds a user to the roster; the first caller seats itself\"),\n  ReadingStep(\"list_threads\", \"the threads the caller may see\"),\n  ReadingStep(\"read_thread\", \"one thread and its posts, if the caller may see it\"),\n  ReadingStep(\"post_reply\", \"a reply under the visibility rule and the reply cap\"),\n  ReadingStep(\"edit_post\", \"an edit under the visibility rule and the edit rule\"),\n  ReadingStep(\"thread_request_issues\", \"the validation issues of an open-thread request\"),\n  ReadingStep(\"parse_thread\", \"a validated open-thread request as a Thread, or its issues\"),\n  ReadingStep(\"open_thread\", \"a new thread from a validated request\"),\n  ReadingStep(\"forum_api\", \"the service: eight routes, each a handler with its permissions\"),\n])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::forum_shape",
        "name": "forum_shape",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Organize::FamilySpec",
        "signatureId": "Yichus/Organize::FamilySpec",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 11452,
          "end": 11605,
          "label": "forum:330:15",
          "source": "FamilySpec(\"handlers\", [\n  \"get_profile\", \"put_profile\", \"grant_moderator\", \"open_thread\",\n  \"list_threads\", \"read_thread\", \"post_reply\", \"edit_post\",\n])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::forum_systems",
        "name": "forum_systems",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Systems::SystemSpec",
        "signatureId": "Yichus/Systems::SystemSpec",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 10635,
          "end": 10896,
          "label": "forum:313:17",
          "source": "SystemSpec([\n  SystemBinding(\"threads\", Postgres(\"forum\", Serializable)),\n  SystemBinding(\"posts\", Postgres(\"forum\", Serializable)),\n  SystemBinding(\"profiles\", Postgres(\"forum\", Serializable)),\n  SystemBinding(\"moderators\", Postgres(\"forum\", Serializable)),\n])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::forum_tables",
        "name": "forum_tables",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Organize::FamilySpec",
        "signatureId": "Yichus/Organize::FamilySpec",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 11339,
          "end": 11436,
          "label": "forum:326:16",
          "source": "FamilySpec(\"tables\", [\n  \"profiles_table\", \"threads_table\", \"posts_table\", \"moderators_table\",\n])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::get_profile",
        "name": "get_profile",
        "package": "Yichus/Examples/Forum",
        "signature": "(Yichus/Data::Db, Yichus/Access::Principal) -> Yichus/IO::IO[Yichus/Service::Response]",
        "signatureId": "(Yichus/Data::Db, Yichus/Access::Principal) -> Yichus/IO::IO[Yichus/Service::Response]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 16737,
          "end": 16979,
          "label": "forum:431:3",
          "source": "Principal(uid, _) = p\n  row <- flat_map(db_read_opt(profiles_table(db), uid))\n  profiles = match row:\n    case None: []\n    case Some(profile): [profile]\n  pure(respond(\"profile\", [jraw(\"profiles\", jarr(map_List(profiles, render_profile)))]))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::grant_moderator",
        "name": "grant_moderator",
        "package": "Yichus/Examples/Forum",
        "signature": "(Yichus/Data::Db, Yichus/Access::Principal, GrantModeratorRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "signatureId": "(Yichus/Data::Db, Yichus/Access::Principal, Yichus/Examples/Forum::GrantModeratorRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 17160,
          "end": 17878,
          "label": "forum:441:3",
          "source": "Principal(uid, _) = p\n  GrantModeratorRequest(target) = req\n  roster <- flat_map(db_read(moderators_table(db), roster_key))\n  match roster:\n    case []:\n      seated <- flat_map(db_write(moderators_table(db), roster_key, [uid]))\n      pure(respond(\"moderators\", [jraw(\"roster\", jarr_of_str(seated))]))\n    case _:\n      if is_moderator(roster, uid):\n        grown = (\n          if member_String(roster, target): roster\n          else: [target, *roster])\n        stored <- flat_map(db_write(moderators_table(db), roster_key, grown))\n        pure(respond(\"moderators\", [jraw(\"roster\", jarr_of_str(stored))]))\n      else: pure(forbid(\"only a moderator grants moderator\", \"Only a moderator can make someone a moderator.\"))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::has_room",
        "name": "has_room",
        "package": "Yichus/Examples/Forum",
        "signature": "(Thread, List[Post]) -> Bool",
        "signatureId": "(Yichus/Examples/Forum::Thread, Bosatsu/Predef::List[Yichus/Examples/Forum::Post]) -> Bosatsu/Predef::Bool",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 8913,
          "end": 8996,
          "label": "forum:271:3",
          "source": "Thread(_, _, _, _, _, reply_cap) = thread\n  int_lt(length_List(replies), reply_cap)"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::int_gt",
        "name": "int_gt",
        "package": "Yichus/Examples/Forum",
        "signature": "(Int, Int) -> Bool",
        "signatureId": "(Bosatsu/Predef::Int, Bosatsu/Predef::Int) -> Bosatsu/Predef::Bool",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 2093,
          "end": 2149,
          "label": "forum:66:3",
          "source": "match cmp_Int(a, b):\n    case GT: True\n    case _: False"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::int_lt",
        "name": "int_lt",
        "package": "Yichus/Examples/Forum",
        "signature": "(Int, Int) -> Bool",
        "signatureId": "(Bosatsu/Predef::Int, Bosatsu/Predef::Int) -> Bosatsu/Predef::Bool",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 1997,
          "end": 2053,
          "label": "forum:61:3",
          "source": "match cmp_Int(a, b):\n    case LT: True\n    case _: False"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::is_blank",
        "name": "is_blank",
        "package": "Yichus/Examples/Forum",
        "signature": "String -> Bool",
        "signatureId": "Bosatsu/Predef::String -> Bosatsu/Predef::Bool",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 2186,
          "end": 2202,
          "label": "forum:71:3",
          "source": "eq_String(s, \"\")"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::is_moderator",
        "name": "is_moderator",
        "package": "Yichus/Examples/Forum",
        "signature": "(List[String], String) -> Bool",
        "signatureId": "(Bosatsu/Predef::List[Bosatsu/Predef::String], Bosatsu/Predef::String) -> Bosatsu/Predef::Bool",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 8096,
          "end": 8122,
          "label": "forum:252:3",
          "source": "member_String(roster, uid)"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::jarr",
        "name": "jarr",
        "package": "Yichus/Examples/Forum",
        "signature": "List[String] -> String",
        "signatureId": "Bosatsu/Predef::List[Bosatsu/Predef::String] -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3679,
          "end": 3727,
          "label": "forum:120:3",
          "source": "concat_String([\"[\", join_with(items, \",\"), \"]\"])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::jarr_of_str",
        "name": "jarr_of_str",
        "package": "Yichus/Examples/Forum",
        "signature": "List[String] -> String",
        "signatureId": "Bosatsu/Predef::List[Bosatsu/Predef::String] -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3779,
          "end": 3807,
          "label": "forum:123:3",
          "source": "jarr(map_List(items, quote))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::jbool",
        "name": "jbool",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, Bool) -> String",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::Bool) -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3509,
          "end": 3539,
          "label": "forum:114:3",
          "source": "jraw(key, bool_literal(value))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::jint",
        "name": "jint",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, Int) -> String",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::Int) -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3212,
          "end": 3266,
          "label": "forum:103:3",
          "source": "concat_String([quote(key), \":\", int_to_String(value)])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::jobj",
        "name": "jobj",
        "package": "Yichus/Examples/Forum",
        "signature": "List[String] -> String",
        "signatureId": "Bosatsu/Predef::List[Bosatsu/Predef::String] -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3585,
          "end": 3634,
          "label": "forum:117:3",
          "source": "concat_String([\"{\", join_with(fields, \",\"), \"}\"])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::join_with",
        "name": "join_with",
        "package": "Yichus/Examples/Forum",
        "signature": "(List[String], String) -> String",
        "signatureId": "(Bosatsu/Predef::List[Bosatsu/Predef::String], Bosatsu/Predef::String) -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 2618,
          "end": 2741,
          "label": "forum:86:3",
          "source": "recur items:\n    case []: \"\"\n    case [last]: last\n    case [head, *tail]: concat_String([head, sep, join_with(tail, sep)])"
        },
        "repetition": [
          {
            "kind": "recursive-lambda",
            "location": {
              "file": "forum",
              "start": 2618,
              "end": 2741,
              "label": "forum:86:3",
              "source": "recur items:\n    case []: \"\"\n    case [last]: last\n    case [head, *tail]: concat_String([head, sep, join_with(tail, sep)])"
            }
          }
        ]
      },
      {
        "id": "Yichus/Examples/Forum::jraw",
        "name": "jraw",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String) -> String",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String) -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3317,
          "end": 3355,
          "label": "forum:106:3",
          "source": "concat_String([quote(key), \":\", body])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::jstr",
        "name": "jstr",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String) -> String",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String) -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3117,
          "end": 3163,
          "label": "forum:100:3",
          "source": "concat_String([quote(key), \":\", quote(value)])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::list_threads",
        "name": "list_threads",
        "package": "Yichus/Examples/Forum",
        "signature": "(Yichus/Data::Db, Yichus/Access::Principal) -> Yichus/IO::IO[Yichus/Service::Response]",
        "signatureId": "(Yichus/Data::Db, Yichus/Access::Principal) -> Yichus/IO::IO[Yichus/Service::Response]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 18363,
          "end": 18703,
          "label": "forum:467:3",
          "source": "Principal(uid, _) = p\n  roster <- flat_map(db_read(moderators_table(db), roster_key))\n  rows <- flat_map(db_query(threads_table(db)))\n  visible = keep_visible(rows, thread -> can_see(uid, roster, thread))\n  pure(respond(\"threads\", [\n    jint(\"count\", length_List(visible)),\n    jraw(\"threads\", jarr(map_List(visible, render_thread))),\n  ]))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::member_String",
        "name": "member_String",
        "package": "Yichus/Examples/Forum",
        "signature": "(List[String], String) -> Bool",
        "signatureId": "(Bosatsu/Predef::List[Bosatsu/Predef::String], Bosatsu/Predef::String) -> Bosatsu/Predef::Bool",
        "exported": false,
        "location": null,
        "repetition": [
          {
            "kind": "compiled-loop",
            "location": null
          }
        ]
      },
      {
        "id": "Yichus/Examples/Forum::merge_issues",
        "name": "merge_issues",
        "package": "Yichus/Examples/Forum",
        "signature": "List[List[Issue]] -> List[Issue]",
        "signatureId": "Bosatsu/Predef::List[Bosatsu/Predef::List[Yichus/Examples/Forum::Issue]] -> Bosatsu/Predef::List[Yichus/Examples/Forum::Issue]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 4347,
          "end": 4385,
          "label": "forum:140:3",
          "source": "flat_map_List(batches, batch -> batch)"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::moderators_table",
        "name": "moderators_table",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Data::Db -> Yichus/Data::Table[List[String]]",
        "signatureId": "Yichus/Data::Db -> Yichus/Data::Table[Bosatsu/Predef::List[Bosatsu/Predef::String]]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 14519,
          "end": 14542,
          "label": "forum:381:3",
          "source": "table(db, \"moderators\")"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::not_found",
        "name": "not_found",
        "package": "Yichus/Examples/Forum",
        "signature": "String -> Yichus/Service::Response",
        "signatureId": "Bosatsu/Predef::String -> Yichus/Service::Response",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 6320,
          "end": 6388,
          "label": "forum:192:3",
          "source": "Response(404, jobj([jstr(\"view\", \"not_found\"), jstr(\"what\", what)]))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::open_thread",
        "name": "open_thread",
        "package": "Yichus/Examples/Forum",
        "signature": "(Yichus/Data::Db, Yichus/Access::Principal, OpenThreadRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "signatureId": "(Yichus/Data::Db, Yichus/Access::Principal, Yichus/Examples/Forum::OpenThreadRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 17961,
          "end": 18303,
          "label": "forum:458:3",
          "source": "Principal(uid, _) = p\n  fresh_id <- flat_map(db_next_id(threads_table(db)))\n  match parse_thread(uid, fresh_id, req):\n    case Failure(issues): pure(reject(issues))\n    case Success(thread):\n      stored <- flat_map(db_write(threads_table(db), fresh_id, thread))\n      pure(respond(\"thread\", [jraw(\"threads\", jarr([render_thread(stored)]))]))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::outcome_of",
        "name": "outcome_of",
        "package": "Yichus/Examples/Forum",
        "signature": "forall a: *. (List[Issue], a) -> Outcome[a]",
        "signatureId": "forall a: *. (Bosatsu/Predef::List[Yichus/Examples/Forum::Issue], a) -> Yichus/Examples/Forum::Outcome[a]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 5222,
          "end": 5291,
          "label": "forum:164:3",
          "source": "match issues:\n    case []: Success(value)\n    case _: Failure(issues)"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::parse_thread",
        "name": "parse_thread",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, String, OpenThreadRequest) -> Outcome[Thread]",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::String, Yichus/Examples/Forum::OpenThreadRequest) -> Yichus/Examples/Forum::Outcome[Yichus/Examples/Forum::Thread]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 15783,
          "end": 15971,
          "label": "forum:412:3",
          "source": "OpenThreadRequest(title, members_only, members, reply_cap) = req\n  outcome_of(thread_request_issues(req),\n    Thread(fresh_id, title, uid, visibility_of(members_only), members, reply_cap))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::post_id_is",
        "name": "post_id_is",
        "package": "Yichus/Examples/Forum",
        "signature": "(Post, String) -> Bool",
        "signatureId": "(Yichus/Examples/Forum::Post, Bosatsu/Predef::String) -> Bosatsu/Predef::Bool",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 9052,
          "end": 9103,
          "label": "forum:275:3",
          "source": "Post(id, _, _, _, _) = post\n  eq_String(id, target)"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::post_reply",
        "name": "post_reply",
        "package": "Yichus/Examples/Forum",
        "signature": "(Yichus/Data::Db, Yichus/Access::Principal, ReplyRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "signatureId": "(Yichus/Data::Db, Yichus/Access::Principal, Yichus/Examples/Forum::ReplyRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 19512,
          "end": 20686,
          "label": "forum:494:3",
          "source": "Principal(uid, _) = p\n  ReplyRequest(thread_id, body) = req\n  match check_text(\"body\", body, 500):\n    case [issue, *more]: pure(reject([issue, *more]))\n    case []:\n      roster <- flat_map(db_read(moderators_table(db), roster_key))\n      row <- flat_map(db_read_opt(threads_table(db), thread_id))\n      match row:\n        case None: pure(not_found(\"thread\"))\n        case Some(thread):\n          if can_see(uid, roster, thread):\n            posts <- flat_map(db_read(posts_table(db), thread_id))\n            if has_room(thread, posts):\n              fresh_id <- flat_map(db_next_id(posts_table(db)))\n              stored <- flat_map(db_write(posts_table(db), thread_id,\n                [*posts, Post(fresh_id, thread_id, uid, body, False)]))\n              pure(respond(\"thread\", [\n                jraw(\"thread\", render_thread(thread)),\n                jint(\"reply_count\", length_List(stored)),\n                jraw(\"posts\", jarr(map_List(stored, render_post))),\n              ]))\n            else: pure(reject([Issue(\"thread_id\", \"thread_full\", \"the thread has reached its reply cap\")]))\n          else: pure(forbid(\"members only\", \"This thread is for its members only.\"))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::posts_table",
        "name": "posts_table",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Data::Db -> Yichus/Data::Table[List[Post]]",
        "signatureId": "Yichus/Data::Db -> Yichus/Data::Table[Bosatsu/Predef::List[Yichus/Examples/Forum::Post]]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 14444,
          "end": 14462,
          "label": "forum:378:3",
          "source": "table(db, \"posts\")"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::profiles_table",
        "name": "profiles_table",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Data::Db -> Yichus/Data::Table[Profile]",
        "signatureId": "Yichus/Data::Db -> Yichus/Data::Table[Yichus/Examples/Forum::Profile]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 14305,
          "end": 14326,
          "label": "forum:372:3",
          "source": "table(db, \"profiles\")"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::put_profile",
        "name": "put_profile",
        "package": "Yichus/Examples/Forum",
        "signature": "(Yichus/Data::Db, Yichus/Access::Principal, PutProfileRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "signatureId": "(Yichus/Data::Db, Yichus/Access::Principal, Yichus/Examples/Forum::PutProfileRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 16341,
          "end": 16678,
          "label": "forum:422:3",
          "source": "Principal(uid, _) = p\n  PutProfileRequest(display_name) = req\n  match check_text(\"display_name\", display_name, 40):\n    case []:\n      stored <- flat_map(db_write(profiles_table(db), uid, Profile(uid, display_name)))\n      pure(respond(\"profile\", [jraw(\"profiles\", jarr([render_profile(stored)]))]))\n    case issues: pure(reject(issues))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::quote",
        "name": "quote",
        "package": "Yichus/Examples/Forum",
        "signature": "String -> String",
        "signatureId": "Bosatsu/Predef::String -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 3035,
          "end": 3065,
          "label": "forum:97:3",
          "source": "concat_String([\"\\\"\", s, \"\\\"\"])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::read_thread",
        "name": "read_thread",
        "package": "Yichus/Examples/Forum",
        "signature": "(Yichus/Data::Db, Yichus/Access::Principal, ReadThreadRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "signatureId": "(Yichus/Data::Db, Yichus/Access::Principal, Yichus/Examples/Forum::ReadThreadRequest) -> Yichus/IO::IO[Yichus/Service::Response]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 18786,
          "end": 19435,
          "label": "forum:477:3",
          "source": "Principal(uid, _) = p\n  ReadThreadRequest(thread_id) = req\n  roster <- flat_map(db_read(moderators_table(db), roster_key))\n  row <- flat_map(db_read_opt(threads_table(db), thread_id))\n  match row:\n    case None: pure(not_found(\"thread\"))\n    case Some(thread):\n      if can_see(uid, roster, thread):\n        posts <- flat_map(db_read(posts_table(db), thread_id))\n        pure(respond(\"thread\", [\n          jraw(\"thread\", render_thread(thread)),\n          jint(\"reply_count\", length_List(posts)),\n          jraw(\"posts\", jarr(map_List(posts, render_post))),\n        ]))\n      else: pure(forbid(\"members only\", \"This thread is for its members only.\"))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::reject",
        "name": "reject",
        "package": "Yichus/Examples/Forum",
        "signature": "List[Issue] -> Yichus/Service::Response",
        "signatureId": "Bosatsu/Predef::List[Yichus/Examples/Forum::Issue] -> Yichus/Service::Response",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 5962,
          "end": 6122,
          "label": "forum:182:3",
          "source": "Response(422, jobj([\n    jstr(\"view\", \"rejected\"),\n    jint(\"issue_count\", length_List(issues)),\n    jraw(\"issues\", jarr(map_List(issues, render_issue))),\n  ]))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::render_issue",
        "name": "render_issue",
        "package": "Yichus/Examples/Forum",
        "signature": "Issue -> String",
        "signatureId": "Yichus/Examples/Forum::Issue -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 5706,
          "end": 5809,
          "label": "forum:175:3",
          "source": "Issue(field, code, hint) = issue\n  jobj([jstr(\"field\", field), jstr(\"code\", code), jstr(\"hint\", hint)])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::render_post",
        "name": "render_post",
        "package": "Yichus/Examples/Forum",
        "signature": "Post -> String",
        "signatureId": "Yichus/Examples/Forum::Post -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 7611,
          "end": 7808,
          "label": "forum:238:3",
          "source": "Post(id, thread_id, author, body, edited) = post\n  jobj([\n    jstr(\"id\", id),\n    jstr(\"thread_id\", thread_id),\n    jstr(\"author\", author),\n    jstr(\"body\", body),\n    jbool(\"edited\", edited),\n  ])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::render_profile",
        "name": "render_profile",
        "package": "Yichus/Examples/Forum",
        "signature": "Profile -> String",
        "signatureId": "Yichus/Examples/Forum::Profile -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 7122,
          "end": 7233,
          "label": "forum:223:3",
          "source": "Profile(user_id, display_name) = profile\n  jobj([jstr(\"user_id\", user_id), jstr(\"display_name\", display_name)])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::render_thread",
        "name": "render_thread",
        "package": "Yichus/Examples/Forum",
        "signature": "Thread -> String",
        "signatureId": "Yichus/Examples/Forum::Thread -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 7282,
          "end": 7568,
          "label": "forum:227:3",
          "source": "Thread(id, title, author, visibility, members, reply_cap) = thread\n  jobj([\n    jstr(\"id\", id),\n    jstr(\"title\", title),\n    jstr(\"author\", author),\n    jstr(\"visibility\", render_visibility(visibility)),\n    jraw(\"members\", jarr_of_str(members)),\n    jint(\"reply_cap\", reply_cap),\n  ])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::render_visibility",
        "name": "render_visibility",
        "package": "Yichus/Examples/Forum",
        "signature": "Visibility -> String",
        "signatureId": "Yichus/Examples/Forum::Visibility -> Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 7012,
          "end": 7070,
          "label": "forum:218:3",
          "source": "match v:\n    case Open: \"open\"\n    case Members: \"members\""
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::replace_post",
        "name": "replace_post",
        "package": "Yichus/Examples/Forum",
        "signature": "(List[Post], Post) -> List[Post]",
        "signatureId": "(Bosatsu/Predef::List[Yichus/Examples/Forum::Post], Yichus/Examples/Forum::Post) -> Bosatsu/Predef::List[Yichus/Examples/Forum::Post]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 9172,
          "end": 9290,
          "label": "forum:279:3",
          "source": "Post(target, _, _, _, _) = edited\n  map_List(posts, post -> (\n    if post_id_is(post, target): edited\n    else: post))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::respond",
        "name": "respond",
        "package": "Yichus/Examples/Forum",
        "signature": "(String, List[String]) -> Yichus/Service::Response",
        "signatureId": "(Bosatsu/Predef::String, Bosatsu/Predef::List[Bosatsu/Predef::String]) -> Yichus/Service::Response",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 5874,
          "end": 5913,
          "label": "forum:179:3",
          "source": "ok(jobj([jstr(\"view\", view), *fields]))"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::roster_key",
        "name": "roster_key",
        "package": "Yichus/Examples/Forum",
        "signature": "String",
        "signatureId": "Bosatsu/Predef::String",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 14557,
          "end": 14565,
          "label": "forum:383:14",
          "source": "\"roster\""
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::thread_request_issues",
        "name": "thread_request_issues",
        "package": "Yichus/Examples/Forum",
        "signature": "OpenThreadRequest -> List[Issue]",
        "signatureId": "Yichus/Examples/Forum::OpenThreadRequest -> Bosatsu/Predef::List[Yichus/Examples/Forum::Issue]",
        "exported": true,
        "location": {
          "file": "forum",
          "start": 15410,
          "end": 15687,
          "label": "forum:404:3",
          "source": "OpenThreadRequest(title, _, members, reply_cap) = req\n  merge_issues([\n    check_text(\"title\", title, 80),\n    flag_if(int_lt(reply_cap, 0), \"reply_cap\", \"negative\", \"a cap is zero or more replies\"),\n    flat_map_List(members, member -> check_text(\"members\", member, 40)),\n  ])"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::threads_table",
        "name": "threads_table",
        "package": "Yichus/Examples/Forum",
        "signature": "Yichus/Data::Db -> Yichus/Data::Table[Thread]",
        "signatureId": "Yichus/Data::Db -> Yichus/Data::Table[Yichus/Examples/Forum::Thread]",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 14374,
          "end": 14394,
          "label": "forum:375:3",
          "source": "table(db, \"threads\")"
        },
        "repetition": []
      },
      {
        "id": "Yichus/Examples/Forum::visibility_of",
        "name": "visibility_of",
        "package": "Yichus/Examples/Forum",
        "signature": "Bool -> Visibility",
        "signatureId": "Bosatsu/Predef::Bool -> Yichus/Examples/Forum::Visibility",
        "exported": false,
        "location": {
          "file": "forum",
          "start": 15154,
          "end": 15217,
          "label": "forum:397:3",
          "source": "match members_only:\n    case True: Members\n    case False: Open"
        },
        "repetition": []
      }
    ],
    "groups": [
      {
        "id": "handlers",
        "label": "Request handlers",
        "parent": null,
        "members": [
          "Yichus/Examples/Forum::put_profile",
          "Yichus/Examples/Forum::get_profile",
          "Yichus/Examples/Forum::grant_moderator",
          "Yichus/Examples/Forum::open_thread",
          "Yichus/Examples/Forum::list_threads",
          "Yichus/Examples/Forum::read_thread",
          "Yichus/Examples/Forum::post_reply",
          "Yichus/Examples/Forum::edit_post"
        ]
      },
      {
        "id": "decisions",
        "label": "Access & validation",
        "parent": null,
        "members": []
      },
      {
        "id": "access",
        "label": "Access decisions",
        "parent": "decisions",
        "members": [
          "Yichus/Examples/Forum::is_moderator",
          "Yichus/Examples/Forum::can_see",
          "Yichus/Examples/Forum::can_edit",
          "Yichus/Examples/Forum::has_room"
        ]
      },
      {
        "id": "validation",
        "label": "Request validation",
        "parent": "decisions",
        "members": [
          "Yichus/Examples/Forum::check_text",
          "Yichus/Examples/Forum::check_blank",
          "Yichus/Examples/Forum::check_clean",
          "Yichus/Examples/Forum::check_max_len",
          "Yichus/Examples/Forum::flag_if",
          "Yichus/Examples/Forum::merge_issues",
          "Yichus/Examples/Forum::outcome_of",
          "Yichus/Examples/Forum::thread_request_issues",
          "Yichus/Examples/Forum::parse_thread",
          "Yichus/Examples/Forum::visibility_of"
        ]
      },
      {
        "id": "representation",
        "label": "Representations",
        "parent": null,
        "members": []
      },
      {
        "id": "response",
        "label": "Response envelopes",
        "parent": "representation",
        "members": [
          "Yichus/Examples/Forum::respond",
          "Yichus/Examples/Forum::reject",
          "Yichus/Examples/Forum::forbid",
          "Yichus/Examples/Forum::not_found"
        ]
      },
      {
        "id": "records",
        "label": "Record rendering",
        "parent": "representation",
        "members": [
          "Yichus/Examples/Forum::render_issue",
          "Yichus/Examples/Forum::render_visibility",
          "Yichus/Examples/Forum::render_profile",
          "Yichus/Examples/Forum::render_thread",
          "Yichus/Examples/Forum::render_post"
        ]
      },
      {
        "id": "json",
        "label": "JSON building blocks",
        "parent": "representation",
        "members": [
          "Yichus/Examples/Forum::quote",
          "Yichus/Examples/Forum::jstr",
          "Yichus/Examples/Forum::jint",
          "Yichus/Examples/Forum::jraw",
          "Yichus/Examples/Forum::bool_literal",
          "Yichus/Examples/Forum::jbool",
          "Yichus/Examples/Forum::jobj",
          "Yichus/Examples/Forum::jarr",
          "Yichus/Examples/Forum::jarr_of_str"
        ]
      },
      {
        "id": "storage",
        "label": "Table handles",
        "parent": null,
        "members": [
          "Yichus/Examples/Forum::profiles_table",
          "Yichus/Examples/Forum::threads_table",
          "Yichus/Examples/Forum::posts_table",
          "Yichus/Examples/Forum::moderators_table",
          "Yichus/Examples/Forum::roster_key"
        ]
      },
      {
        "id": "collections",
        "label": "Collection operations",
        "parent": null,
        "members": [
          "Yichus/Examples/Forum::post_id_is",
          "Yichus/Examples/Forum::replace_post",
          "Yichus/Examples/Forum::find_post",
          "Yichus/Examples/Forum::member_String",
          "Yichus/Examples/Forum::join_with",
          "Yichus/Examples/Forum::int_lt",
          "Yichus/Examples/Forum::int_gt",
          "Yichus/Examples/Forum::is_blank",
          "Yichus/Examples/Forum::contains_String"
        ]
      },
      {
        "id": "configuration",
        "label": "Service declarations",
        "parent": null,
        "members": [
          "Yichus/Examples/Forum::forum_api",
          "Yichus/Examples/Forum::access_rules",
          "Yichus/Examples/Forum::forum_systems",
          "Yichus/Examples/Forum::forum_tables",
          "Yichus/Examples/Forum::forum_shape",
          "Yichus/Examples/Forum::forum_reading"
        ]
      }
    ],
    "unassigned": [],
    "references": [
      {
        "from": "Yichus/Examples/Forum::can_edit",
        "to": "Yichus/Examples/Forum::is_moderator",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 8736,
            "end": 8748,
            "label": "forum:266:30",
            "source": "is_moderator"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::can_see",
        "to": "Yichus/Examples/Forum::is_moderator",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 8508,
            "end": 8520,
            "label": "forum:261:66",
            "source": "is_moderator"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::can_see",
        "to": "Yichus/Examples/Forum::member_String",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 8479,
            "end": 8492,
            "label": "forum:261:37",
            "source": "member_String"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_blank",
        "to": "Yichus/Examples/Forum::flag_if",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 4451,
            "end": 4458,
            "label": "forum:143:3",
            "source": "flag_if"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_blank",
        "to": "Yichus/Examples/Forum::is_blank",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 4459,
            "end": 4467,
            "label": "forum:143:11",
            "source": "is_blank"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_clean",
        "to": "Yichus/Examples/Forum::contains_String",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 4595,
            "end": 4610,
            "label": "forum:146:11",
            "source": "contains_String"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_clean",
        "to": "Yichus/Examples/Forum::flag_if",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 4587,
            "end": 4594,
            "label": "forum:146:3",
            "source": "flag_if"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_max_len",
        "to": "Yichus/Examples/Forum::check_clean",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 4956,
            "end": 4967,
            "label": "forum:154:5",
            "source": "check_clean"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_max_len",
        "to": "Yichus/Examples/Forum::flag_if",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 4846,
            "end": 4853,
            "label": "forum:152:5",
            "source": "flag_if"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_max_len",
        "to": "Yichus/Examples/Forum::int_gt",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 4789,
            "end": 4795,
            "label": "forum:150:10",
            "source": "int_gt"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_max_len",
        "to": "Yichus/Examples/Forum::merge_issues",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 4827,
            "end": 4839,
            "label": "forum:151:3",
            "source": "merge_issues"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_text",
        "to": "Yichus/Examples/Forum::check_blank",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5083,
            "end": 5094,
            "label": "forum:159:5",
            "source": "check_blank"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_text",
        "to": "Yichus/Examples/Forum::check_max_len",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5114,
            "end": 5127,
            "label": "forum:160:5",
            "source": "check_max_len"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::check_text",
        "to": "Yichus/Examples/Forum::merge_issues",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5064,
            "end": 5076,
            "label": "forum:158:3",
            "source": "merge_issues"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::can_edit",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21419,
            "end": 21427,
            "label": "forum:534:20",
            "source": "can_edit"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::can_see",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21178,
            "end": 21185,
            "label": "forum:529:14",
            "source": "can_see"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::check_text",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20845,
            "end": 20855,
            "label": "forum:521:9",
            "source": "check_text"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::find_post",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21293,
            "end": 21302,
            "label": "forum:531:19",
            "source": "find_post"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::forbid",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21945,
            "end": 21951,
            "label": "forum:543:28",
            "source": "forbid"
          },
          {
            "file": "forum",
            "start": 22051,
            "end": 22057,
            "label": "forum:544:22",
            "source": "forbid"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21858,
            "end": 21862,
            "label": "forum:541:35",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::jint",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21782,
            "end": 21786,
            "label": "forum:540:21",
            "source": "jint"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21723,
            "end": 21727,
            "label": "forum:539:21",
            "source": "jraw"
          },
          {
            "file": "forum",
            "start": 21844,
            "end": 21848,
            "label": "forum:541:21",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::moderators_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20976,
            "end": 20992,
            "label": "forum:524:34",
            "source": "moderators_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::not_found",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21117,
            "end": 21126,
            "label": "forum:527:25",
            "source": "not_found"
          },
          {
            "file": "forum",
            "start": 21350,
            "end": 21359,
            "label": "forum:532:31",
            "source": "not_found"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::posts_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21246,
            "end": 21257,
            "label": "forum:530:39",
            "source": "posts_table"
          },
          {
            "file": "forum",
            "start": 21544,
            "end": 21555,
            "label": "forum:536:47",
            "source": "posts_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::reject",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20906,
            "end": 20912,
            "label": "forum:522:31",
            "source": "reject"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::render_post",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21880,
            "end": 21891,
            "label": "forum:541:57",
            "source": "render_post"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::render_thread",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21738,
            "end": 21751,
            "label": "forum:539:36",
            "source": "render_thread"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::replace_post",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21592,
            "end": 21604,
            "label": "forum:537:21",
            "source": "replace_post"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::respond",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21683,
            "end": 21690,
            "label": "forum:538:24",
            "source": "respond"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::roster_key",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20998,
            "end": 21008,
            "label": "forum:524:56",
            "source": "roster_key"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::edit_post",
        "to": "Yichus/Examples/Forum::threads_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 21045,
            "end": 21058,
            "label": "forum:525:35",
            "source": "threads_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::find_post",
        "to": "Yichus/Examples/Forum::post_id_is",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 9423,
            "end": 9433,
            "label": "forum:288:10",
            "source": "post_id_is"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forbid",
        "to": "Yichus/Examples/Forum::jobj",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 6195,
            "end": 6199,
            "label": "forum:189:17",
            "source": "jobj"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forbid",
        "to": "Yichus/Examples/Forum::jstr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 6201,
            "end": 6205,
            "label": "forum:189:23",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 6228,
            "end": 6232,
            "label": "forum:189:50",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 6248,
            "end": 6252,
            "label": "forum:189:70",
            "source": "jstr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forum_api",
        "to": "Yichus/Examples/Forum::edit_post",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 23055,
            "end": 23064,
            "label": "forum:561:47",
            "source": "edit_post"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forum_api",
        "to": "Yichus/Examples/Forum::get_profile",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 22201,
            "end": 22212,
            "label": "forum:549:46",
            "source": "get_profile"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forum_api",
        "to": "Yichus/Examples/Forum::grant_moderator",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 22387,
            "end": 22402,
            "label": "forum:551:59",
            "source": "grant_moderator"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forum_api",
        "to": "Yichus/Examples/Forum::list_threads",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 22627,
            "end": 22639,
            "label": "forum:555:47",
            "source": "list_threads"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forum_api",
        "to": "Yichus/Examples/Forum::open_thread",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 22513,
            "end": 22524,
            "label": "forum:553:51",
            "source": "open_thread"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forum_api",
        "to": "Yichus/Examples/Forum::post_reply",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 22882,
            "end": 22892,
            "label": "forum:559:49",
            "source": "post_reply"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forum_api",
        "to": "Yichus/Examples/Forum::put_profile",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 22289,
            "end": 22300,
            "label": "forum:550:50",
            "source": "put_profile"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::forum_api",
        "to": "Yichus/Examples/Forum::read_thread",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 22747,
            "end": 22758,
            "label": "forum:557:51",
            "source": "read_thread"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::get_profile",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16935,
            "end": 16939,
            "label": "forum:436:45",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::get_profile",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16918,
            "end": 16922,
            "label": "forum:436:28",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::get_profile",
        "to": "Yichus/Examples/Forum::profiles_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16789,
            "end": 16803,
            "label": "forum:432:31",
            "source": "profiles_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::get_profile",
        "to": "Yichus/Examples/Forum::render_profile",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16959,
            "end": 16973,
            "label": "forum:436:69",
            "source": "render_profile"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::get_profile",
        "to": "Yichus/Examples/Forum::respond",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16898,
            "end": 16905,
            "label": "forum:436:8",
            "source": "respond"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::grant_moderator",
        "to": "Yichus/Examples/Forum::forbid",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 17784,
            "end": 17790,
            "label": "forum:455:18",
            "source": "forbid"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::grant_moderator",
        "to": "Yichus/Examples/Forum::is_moderator",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 17483,
            "end": 17495,
            "label": "forum:449:10",
            "source": "is_moderator"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::grant_moderator",
        "to": "Yichus/Examples/Forum::jarr_of_str",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 17438,
            "end": 17449,
            "label": "forum:447:50",
            "source": "jarr_of_str"
          },
          {
            "file": "forum",
            "start": 17743,
            "end": 17754,
            "label": "forum:454:52",
            "source": "jarr_of_str"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::grant_moderator",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 17423,
            "end": 17427,
            "label": "forum:447:35",
            "source": "jraw"
          },
          {
            "file": "forum",
            "start": 17728,
            "end": 17732,
            "label": "forum:454:37",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::grant_moderator",
        "to": "Yichus/Examples/Forum::member_String",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 17541,
            "end": 17554,
            "label": "forum:451:14",
            "source": "member_String"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::grant_moderator",
        "to": "Yichus/Examples/Forum::moderators_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 17249,
            "end": 17265,
            "label": "forum:443:30",
            "source": "moderators_table"
          },
          {
            "file": "forum",
            "start": 17347,
            "end": 17363,
            "label": "forum:446:35",
            "source": "moderators_table"
          },
          {
            "file": "forum",
            "start": 17650,
            "end": 17666,
            "label": "forum:453:37",
            "source": "moderators_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::grant_moderator",
        "to": "Yichus/Examples/Forum::respond",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 17400,
            "end": 17407,
            "label": "forum:447:12",
            "source": "respond"
          },
          {
            "file": "forum",
            "start": 17705,
            "end": 17712,
            "label": "forum:454:14",
            "source": "respond"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::grant_moderator",
        "to": "Yichus/Examples/Forum::roster_key",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 17271,
            "end": 17281,
            "label": "forum:443:52",
            "source": "roster_key"
          },
          {
            "file": "forum",
            "start": 17369,
            "end": 17379,
            "label": "forum:446:57",
            "source": "roster_key"
          },
          {
            "file": "forum",
            "start": 17672,
            "end": 17682,
            "label": "forum:453:59",
            "source": "roster_key"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::has_room",
        "to": "Yichus/Examples/Forum::int_lt",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 8957,
            "end": 8963,
            "label": "forum:272:3",
            "source": "int_lt"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::is_moderator",
        "to": "Yichus/Examples/Forum::member_String",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 8096,
            "end": 8109,
            "label": "forum:252:3",
            "source": "member_String"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jarr",
        "to": "Yichus/Examples/Forum::join_with",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3699,
            "end": 3708,
            "label": "forum:120:23",
            "source": "join_with"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jarr_of_str",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3779,
            "end": 3783,
            "label": "forum:123:3",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jarr_of_str",
        "to": "Yichus/Examples/Forum::quote",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3800,
            "end": 3805,
            "label": "forum:123:24",
            "source": "quote"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jbool",
        "to": "Yichus/Examples/Forum::bool_literal",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3519,
            "end": 3531,
            "label": "forum:114:13",
            "source": "bool_literal"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jbool",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3509,
            "end": 3513,
            "label": "forum:114:3",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jint",
        "to": "Yichus/Examples/Forum::quote",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3227,
            "end": 3232,
            "label": "forum:103:18",
            "source": "quote"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jobj",
        "to": "Yichus/Examples/Forum::join_with",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3605,
            "end": 3614,
            "label": "forum:117:23",
            "source": "join_with"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jraw",
        "to": "Yichus/Examples/Forum::quote",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3332,
            "end": 3337,
            "label": "forum:106:18",
            "source": "quote"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::jstr",
        "to": "Yichus/Examples/Forum::quote",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 3132,
            "end": 3137,
            "label": "forum:100:18",
            "source": "quote"
          },
          {
            "file": "forum",
            "start": 3149,
            "end": 3154,
            "label": "forum:100:35",
            "source": "quote"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::can_see",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18538,
            "end": 18545,
            "label": "forum:470:42",
            "source": "can_see"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18657,
            "end": 18661,
            "label": "forum:473:21",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::jint",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18600,
            "end": 18604,
            "label": "forum:472:5",
            "source": "jint"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18641,
            "end": 18645,
            "label": "forum:473:5",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::moderators_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18414,
            "end": 18430,
            "label": "forum:468:30",
            "source": "moderators_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::render_thread",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18680,
            "end": 18693,
            "label": "forum:473:44",
            "source": "render_thread"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::respond",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18575,
            "end": 18582,
            "label": "forum:471:8",
            "source": "respond"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::roster_key",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18436,
            "end": 18446,
            "label": "forum:468:52",
            "source": "roster_key"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::list_threads",
        "to": "Yichus/Examples/Forum::threads_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18477,
            "end": 18490,
            "label": "forum:469:29",
            "source": "threads_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::not_found",
        "to": "Yichus/Examples/Forum::jobj",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 6334,
            "end": 6338,
            "label": "forum:192:17",
            "source": "jobj"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::not_found",
        "to": "Yichus/Examples/Forum::jstr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 6340,
            "end": 6344,
            "label": "forum:192:23",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 6367,
            "end": 6371,
            "label": "forum:192:50",
            "source": "jstr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::open_thread",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18270,
            "end": 18274,
            "label": "forum:464:47",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::open_thread",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18254,
            "end": 18258,
            "label": "forum:464:31",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::open_thread",
        "to": "Yichus/Examples/Forum::parse_thread",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18045,
            "end": 18057,
            "label": "forum:460:9",
            "source": "parse_thread"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::open_thread",
        "to": "Yichus/Examples/Forum::reject",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18110,
            "end": 18116,
            "label": "forum:461:32",
            "source": "reject"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::open_thread",
        "to": "Yichus/Examples/Forum::render_thread",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18276,
            "end": 18289,
            "label": "forum:464:53",
            "source": "render_thread"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::open_thread",
        "to": "Yichus/Examples/Forum::respond",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18235,
            "end": 18242,
            "label": "forum:464:12",
            "source": "respond"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::open_thread",
        "to": "Yichus/Examples/Forum::threads_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18017,
            "end": 18030,
            "label": "forum:459:35",
            "source": "threads_table"
          },
          {
            "file": "forum",
            "start": 18186,
            "end": 18199,
            "label": "forum:463:35",
            "source": "threads_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::parse_thread",
        "to": "Yichus/Examples/Forum::outcome_of",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 15850,
            "end": 15860,
            "label": "forum:413:3",
            "source": "outcome_of"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::parse_thread",
        "to": "Yichus/Examples/Forum::thread_request_issues",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 15861,
            "end": 15882,
            "label": "forum:413:14",
            "source": "thread_request_issues"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::parse_thread",
        "to": "Yichus/Examples/Forum::visibility_of",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 15922,
            "end": 15935,
            "label": "forum:414:34",
            "source": "visibility_of"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::can_see",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19913,
            "end": 19920,
            "label": "forum:504:14",
            "source": "can_see"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::check_text",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19580,
            "end": 19590,
            "label": "forum:496:9",
            "source": "check_text"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::forbid",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20623,
            "end": 20629,
            "label": "forum:516:22",
            "source": "forbid"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::has_room",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20025,
            "end": 20033,
            "label": "forum:506:16",
            "source": "has_room"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20438,
            "end": 20442,
            "label": "forum:513:31",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::jint",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20366,
            "end": 20370,
            "label": "forum:512:17",
            "source": "jint"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20311,
            "end": 20315,
            "label": "forum:511:17",
            "source": "jraw"
          },
          {
            "file": "forum",
            "start": 20424,
            "end": 20428,
            "label": "forum:513:17",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::moderators_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19711,
            "end": 19727,
            "label": "forum:499:34",
            "source": "moderators_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::not_found",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19852,
            "end": 19861,
            "label": "forum:502:25",
            "source": "not_found"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::posts_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19981,
            "end": 19992,
            "label": "forum:505:39",
            "source": "posts_table"
          },
          {
            "file": "forum",
            "start": 20096,
            "end": 20107,
            "label": "forum:507:47",
            "source": "posts_table"
          },
          {
            "file": "forum",
            "start": 20156,
            "end": 20167,
            "label": "forum:508:43",
            "source": "posts_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::reject",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19641,
            "end": 19647,
            "label": "forum:497:31",
            "source": "reject"
          },
          {
            "file": "forum",
            "start": 20517,
            "end": 20523,
            "label": "forum:515:24",
            "source": "reject"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::render_post",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20460,
            "end": 20471,
            "label": "forum:513:53",
            "source": "render_post"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::render_thread",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20326,
            "end": 20339,
            "label": "forum:511:32",
            "source": "render_thread"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::respond",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 20275,
            "end": 20282,
            "label": "forum:510:20",
            "source": "respond"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::roster_key",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19733,
            "end": 19743,
            "label": "forum:499:56",
            "source": "roster_key"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::post_reply",
        "to": "Yichus/Examples/Forum::threads_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19780,
            "end": 19793,
            "label": "forum:500:35",
            "source": "threads_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::put_profile",
        "to": "Yichus/Examples/Forum::check_text",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16411,
            "end": 16421,
            "label": "forum:424:9",
            "source": "check_text"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::put_profile",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16606,
            "end": 16610,
            "label": "forum:427:49",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::put_profile",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16589,
            "end": 16593,
            "label": "forum:427:32",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::put_profile",
        "to": "Yichus/Examples/Forum::profiles_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16504,
            "end": 16518,
            "label": "forum:426:35",
            "source": "profiles_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::put_profile",
        "to": "Yichus/Examples/Forum::reject",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16663,
            "end": 16669,
            "label": "forum:428:23",
            "source": "reject"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::put_profile",
        "to": "Yichus/Examples/Forum::render_profile",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16612,
            "end": 16626,
            "label": "forum:427:55",
            "source": "render_profile"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::put_profile",
        "to": "Yichus/Examples/Forum::respond",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 16569,
            "end": 16576,
            "label": "forum:427:12",
            "source": "respond"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::can_see",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19056,
            "end": 19063,
            "label": "forum:484:10",
            "source": "can_see"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::forbid",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19372,
            "end": 19378,
            "label": "forum:491:18",
            "source": "forbid"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19306,
            "end": 19310,
            "label": "forum:489:25",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::jint",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19241,
            "end": 19245,
            "label": "forum:488:11",
            "source": "jint"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19192,
            "end": 19196,
            "label": "forum:487:11",
            "source": "jraw"
          },
          {
            "file": "forum",
            "start": 19292,
            "end": 19296,
            "label": "forum:489:11",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::moderators_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18874,
            "end": 18890,
            "label": "forum:479:30",
            "source": "moderators_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::not_found",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19003,
            "end": 19012,
            "label": "forum:482:21",
            "source": "not_found"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::posts_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19120,
            "end": 19131,
            "label": "forum:485:35",
            "source": "posts_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::render_post",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19327,
            "end": 19338,
            "label": "forum:489:46",
            "source": "render_post"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::render_thread",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19207,
            "end": 19220,
            "label": "forum:487:26",
            "source": "render_thread"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::respond",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 19162,
            "end": 19169,
            "label": "forum:486:14",
            "source": "respond"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::roster_key",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18896,
            "end": 18906,
            "label": "forum:479:52",
            "source": "roster_key"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::read_thread",
        "to": "Yichus/Examples/Forum::threads_table",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 18939,
            "end": 18952,
            "label": "forum:480:31",
            "source": "threads_table"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::reject",
        "to": "Yichus/Examples/Forum::jarr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 6078,
            "end": 6082,
            "label": "forum:185:20",
            "source": "jarr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::reject",
        "to": "Yichus/Examples/Forum::jint",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 6017,
            "end": 6021,
            "label": "forum:184:5",
            "source": "jint"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::reject",
        "to": "Yichus/Examples/Forum::jobj",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5976,
            "end": 5980,
            "label": "forum:182:17",
            "source": "jobj"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::reject",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 6063,
            "end": 6067,
            "label": "forum:185:5",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::reject",
        "to": "Yichus/Examples/Forum::jstr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5987,
            "end": 5991,
            "label": "forum:183:5",
            "source": "jstr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::reject",
        "to": "Yichus/Examples/Forum::render_issue",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 6100,
            "end": 6112,
            "label": "forum:185:42",
            "source": "render_issue"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_issue",
        "to": "Yichus/Examples/Forum::jobj",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5741,
            "end": 5745,
            "label": "forum:176:3",
            "source": "jobj"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_issue",
        "to": "Yichus/Examples/Forum::jstr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5747,
            "end": 5751,
            "label": "forum:176:9",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 5769,
            "end": 5773,
            "label": "forum:176:31",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 5789,
            "end": 5793,
            "label": "forum:176:51",
            "source": "jstr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_post",
        "to": "Yichus/Examples/Forum::jbool",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7779,
            "end": 7784,
            "label": "forum:244:5",
            "source": "jbool"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_post",
        "to": "Yichus/Examples/Forum::jobj",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7662,
            "end": 7666,
            "label": "forum:239:3",
            "source": "jobj"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_post",
        "to": "Yichus/Examples/Forum::jstr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7673,
            "end": 7677,
            "label": "forum:240:5",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 7693,
            "end": 7697,
            "label": "forum:241:5",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 7727,
            "end": 7731,
            "label": "forum:242:5",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 7755,
            "end": 7759,
            "label": "forum:243:5",
            "source": "jstr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_profile",
        "to": "Yichus/Examples/Forum::jobj",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7165,
            "end": 7169,
            "label": "forum:224:3",
            "source": "jobj"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_profile",
        "to": "Yichus/Examples/Forum::jstr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7171,
            "end": 7175,
            "label": "forum:224:9",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 7197,
            "end": 7201,
            "label": "forum:224:35",
            "source": "jstr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_thread",
        "to": "Yichus/Examples/Forum::jarr_of_str",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7507,
            "end": 7518,
            "label": "forum:233:21",
            "source": "jarr_of_str"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_thread",
        "to": "Yichus/Examples/Forum::jint",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7534,
            "end": 7538,
            "label": "forum:234:5",
            "source": "jint"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_thread",
        "to": "Yichus/Examples/Forum::jobj",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7351,
            "end": 7355,
            "label": "forum:228:3",
            "source": "jobj"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_thread",
        "to": "Yichus/Examples/Forum::jraw",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7491,
            "end": 7495,
            "label": "forum:233:5",
            "source": "jraw"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_thread",
        "to": "Yichus/Examples/Forum::jstr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7362,
            "end": 7366,
            "label": "forum:229:5",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 7382,
            "end": 7386,
            "label": "forum:230:5",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 7408,
            "end": 7412,
            "label": "forum:231:5",
            "source": "jstr"
          },
          {
            "file": "forum",
            "start": 7436,
            "end": 7440,
            "label": "forum:232:5",
            "source": "jstr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::render_thread",
        "to": "Yichus/Examples/Forum::render_visibility",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 7455,
            "end": 7472,
            "label": "forum:232:24",
            "source": "render_visibility"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::replace_post",
        "to": "Yichus/Examples/Forum::post_id_is",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 9241,
            "end": 9251,
            "label": "forum:281:8",
            "source": "post_id_is"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::respond",
        "to": "Yichus/Examples/Forum::jobj",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5877,
            "end": 5881,
            "label": "forum:179:6",
            "source": "jobj"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::respond",
        "to": "Yichus/Examples/Forum::jstr",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 5883,
            "end": 5887,
            "label": "forum:179:12",
            "source": "jstr"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::thread_request_issues",
        "to": "Yichus/Examples/Forum::check_text",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 15485,
            "end": 15495,
            "label": "forum:406:5",
            "source": "check_text"
          },
          {
            "file": "forum",
            "start": 15647,
            "end": 15657,
            "label": "forum:408:38",
            "source": "check_text"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::thread_request_issues",
        "to": "Yichus/Examples/Forum::flag_if",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 15521,
            "end": 15528,
            "label": "forum:407:5",
            "source": "flag_if"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::thread_request_issues",
        "to": "Yichus/Examples/Forum::int_lt",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 15529,
            "end": 15535,
            "label": "forum:407:13",
            "source": "int_lt"
          }
        ]
      },
      {
        "from": "Yichus/Examples/Forum::thread_request_issues",
        "to": "Yichus/Examples/Forum::merge_issues",
        "kind": "user-reference",
        "locations": [
          {
            "file": "forum",
            "start": 15466,
            "end": 15478,
            "label": "forum:405:3",
            "source": "merge_issues"
          }
        ]
      }
    ],
    "effects": [
      {
        "binding": "Yichus/Examples/Forum::edit_post",
        "kind": "DbRead",
        "operation": "db_read",
        "resource": "moderators",
        "location": {
          "file": "forum",
          "start": 20968,
          "end": 21009,
          "label": "forum:524:26",
          "source": "db_read(moderators_table(db), roster_key)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::edit_post",
        "kind": "DbRead",
        "operation": "db_read_opt",
        "resource": "threads",
        "location": {
          "file": "forum",
          "start": 21033,
          "end": 21074,
          "label": "forum:525:23",
          "source": "db_read_opt(threads_table(db), thread_id)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::edit_post",
        "kind": "DbRead",
        "operation": "db_read",
        "resource": "posts",
        "location": {
          "file": "forum",
          "start": 21238,
          "end": 21273,
          "label": "forum:530:31",
          "source": "db_read(posts_table(db), thread_id)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::edit_post",
        "kind": "DbWrite",
        "operation": "db_write",
        "resource": "posts",
        "location": {
          "file": "forum",
          "start": 21535,
          "end": 21658,
          "label": "forum:536:38",
          "source": "db_write(posts_table(db), thread_id,\n                    replace_post(posts, Post(post_id, thread_id, author, body, True)))"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::get_profile",
        "kind": "DbRead",
        "operation": "db_read_opt",
        "resource": "profiles",
        "location": {
          "file": "forum",
          "start": 16777,
          "end": 16813,
          "label": "forum:432:19",
          "source": "db_read_opt(profiles_table(db), uid)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::grant_moderator",
        "kind": "DbRead",
        "operation": "db_read",
        "resource": "moderators",
        "location": {
          "file": "forum",
          "start": 17241,
          "end": 17282,
          "label": "forum:443:22",
          "source": "db_read(moderators_table(db), roster_key)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::grant_moderator",
        "kind": "DbWrite",
        "operation": "db_write",
        "resource": "moderators",
        "location": {
          "file": "forum",
          "start": 17338,
          "end": 17387,
          "label": "forum:446:26",
          "source": "db_write(moderators_table(db), roster_key, [uid])"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::grant_moderator",
        "kind": "DbWrite",
        "operation": "db_write",
        "resource": "moderators",
        "location": {
          "file": "forum",
          "start": 17641,
          "end": 17690,
          "label": "forum:453:28",
          "source": "db_write(moderators_table(db), roster_key, grown)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::list_threads",
        "kind": "DbRead",
        "operation": "db_read",
        "resource": "moderators",
        "location": {
          "file": "forum",
          "start": 18406,
          "end": 18447,
          "label": "forum:468:22",
          "source": "db_read(moderators_table(db), roster_key)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::list_threads",
        "kind": "DbQuery",
        "operation": "db_query",
        "resource": "threads",
        "location": {
          "file": "forum",
          "start": 18468,
          "end": 18495,
          "label": "forum:469:20",
          "source": "db_query(threads_table(db))"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::open_thread",
        "kind": "DbNextId",
        "operation": "db_next_id",
        "resource": "threads",
        "location": {
          "file": "forum",
          "start": 18006,
          "end": 18035,
          "label": "forum:459:24",
          "source": "db_next_id(threads_table(db))"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::open_thread",
        "kind": "DbWrite",
        "operation": "db_write",
        "resource": "threads",
        "location": {
          "file": "forum",
          "start": 18177,
          "end": 18222,
          "label": "forum:463:26",
          "source": "db_write(threads_table(db), fresh_id, thread)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::post_reply",
        "kind": "DbRead",
        "operation": "db_read",
        "resource": "moderators",
        "location": {
          "file": "forum",
          "start": 19703,
          "end": 19744,
          "label": "forum:499:26",
          "source": "db_read(moderators_table(db), roster_key)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::post_reply",
        "kind": "DbRead",
        "operation": "db_read_opt",
        "resource": "threads",
        "location": {
          "file": "forum",
          "start": 19768,
          "end": 19809,
          "label": "forum:500:23",
          "source": "db_read_opt(threads_table(db), thread_id)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::post_reply",
        "kind": "DbRead",
        "operation": "db_read",
        "resource": "posts",
        "location": {
          "file": "forum",
          "start": 19973,
          "end": 20008,
          "label": "forum:505:31",
          "source": "db_read(posts_table(db), thread_id)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::post_reply",
        "kind": "DbNextId",
        "operation": "db_next_id",
        "resource": "posts",
        "location": {
          "file": "forum",
          "start": 20085,
          "end": 20112,
          "label": "forum:507:36",
          "source": "db_next_id(posts_table(db))"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::post_reply",
        "kind": "DbWrite",
        "operation": "db_write",
        "resource": "posts",
        "location": {
          "file": "forum",
          "start": 20147,
          "end": 20254,
          "label": "forum:508:34",
          "source": "db_write(posts_table(db), thread_id,\n                [*posts, Post(fresh_id, thread_id, uid, body, False)])"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::put_profile",
        "kind": "DbWrite",
        "operation": "db_write",
        "resource": "profiles",
        "location": {
          "file": "forum",
          "start": 16495,
          "end": 16556,
          "label": "forum:426:26",
          "source": "db_write(profiles_table(db), uid, Profile(uid, display_name))"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::read_thread",
        "kind": "DbRead",
        "operation": "db_read",
        "resource": "moderators",
        "location": {
          "file": "forum",
          "start": 18866,
          "end": 18907,
          "label": "forum:479:22",
          "source": "db_read(moderators_table(db), roster_key)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::read_thread",
        "kind": "DbRead",
        "operation": "db_read_opt",
        "resource": "threads",
        "location": {
          "file": "forum",
          "start": 18927,
          "end": 18968,
          "label": "forum:480:19",
          "source": "db_read_opt(threads_table(db), thread_id)"
        }
      },
      {
        "binding": "Yichus/Examples/Forum::read_thread",
        "kind": "DbRead",
        "operation": "db_read",
        "resource": "posts",
        "location": {
          "file": "forum",
          "start": 19112,
          "end": 19147,
          "label": "forum:485:27",
          "source": "db_read(posts_table(db), thread_id)"
        }
      }
    ],
    "access": {
      "proven": true,
      "specError": null,
      "findings": [
        {
          "package": "Yichus/Examples/Forum",
          "binding": "get_profile",
          "resource": "profiles",
          "operation": "db_read_opt",
          "kind": "OwnerKeyProven",
          "status": "holds",
          "detail": "key derives from the authenticated Principal (user_id or owner_key)"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "put_profile",
          "resource": "profiles",
          "operation": "db_write",
          "kind": "OwnerKeyProven",
          "status": "holds",
          "detail": "key derives from the authenticated Principal (user_id or owner_key)"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "grant_moderator",
          "resource": "moderators",
          "operation": "db_read",
          "kind": "PublicResource",
          "status": "holds",
          "detail": "resource \"moderators\" is Public; no key discipline required"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "grant_moderator",
          "resource": "moderators",
          "operation": "db_write",
          "kind": "PublicResource",
          "status": "holds",
          "detail": "resource \"moderators\" is Public; no key discipline required"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "grant_moderator",
          "resource": "moderators",
          "operation": "db_write",
          "kind": "PublicResource",
          "status": "holds",
          "detail": "resource \"moderators\" is Public; no key discipline required"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "open_thread",
          "resource": "threads",
          "operation": "db_next_id",
          "kind": "GuardedCreate",
          "status": "holds",
          "detail": "db_next_id on \"threads\" touches no existing row"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "open_thread",
          "resource": "threads",
          "operation": "db_write",
          "kind": "GuardedCreate",
          "status": "holds",
          "detail": "key is a fresh id from db_next_id on \"threads\": a create"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "list_threads",
          "resource": "moderators",
          "operation": "db_read",
          "kind": "PublicResource",
          "status": "holds",
          "detail": "resource \"moderators\" is Public; no key discipline required"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "list_threads",
          "resource": "threads",
          "operation": "db_query",
          "kind": "GuardedRead",
          "status": "holds",
          "detail": "rows of \"threads\" are tainted from here; every use must sit under can_see"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "list_threads",
          "resource": "threads",
          "operation": "keep_visible",
          "kind": "GuardProven",
          "status": "holds",
          "detail": "rows of \"threads\" filtered by can_see(Principal.user_id, row of threads)"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "read_thread",
          "resource": "moderators",
          "operation": "db_read",
          "kind": "PublicResource",
          "status": "holds",
          "detail": "resource \"moderators\" is Public; no key discipline required"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "read_thread",
          "resource": "threads",
          "operation": "db_read_opt",
          "kind": "GuardedRead",
          "status": "holds",
          "detail": "rows of \"threads\" are tainted from here; every use must sit under can_see"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "read_thread",
          "resource": "posts",
          "operation": "db_read",
          "kind": "GuardedRead",
          "status": "holds",
          "detail": "rows of \"posts\" are tainted from here; every use must sit under can_see or can_edit"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "post_reply",
          "resource": "moderators",
          "operation": "db_read",
          "kind": "PublicResource",
          "status": "holds",
          "detail": "resource \"moderators\" is Public; no key discipline required"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "post_reply",
          "resource": "threads",
          "operation": "db_read_opt",
          "kind": "GuardedRead",
          "status": "holds",
          "detail": "rows of \"threads\" are tainted from here; every use must sit under can_see"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "post_reply",
          "resource": "posts",
          "operation": "db_read",
          "kind": "GuardedRead",
          "status": "holds",
          "detail": "rows of \"posts\" are tainted from here; every use must sit under can_see or can_edit"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "post_reply",
          "resource": "posts",
          "operation": "db_next_id",
          "kind": "GuardedCreate",
          "status": "holds",
          "detail": "db_next_id on \"posts\" touches no existing row"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "post_reply",
          "resource": "posts",
          "operation": "db_write",
          "kind": "GuardProven",
          "status": "holds",
          "detail": "dominated by can_see(Principal.user_id, row of threads), on the row it was applied to (key thread_id)"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "edit_post",
          "resource": "moderators",
          "operation": "db_read",
          "kind": "PublicResource",
          "status": "holds",
          "detail": "resource \"moderators\" is Public; no key discipline required"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "edit_post",
          "resource": "threads",
          "operation": "db_read_opt",
          "kind": "GuardedRead",
          "status": "holds",
          "detail": "rows of \"threads\" are tainted from here; every use must sit under can_see"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "edit_post",
          "resource": "posts",
          "operation": "db_read",
          "kind": "GuardedRead",
          "status": "holds",
          "detail": "rows of \"posts\" are tainted from here; every use must sit under can_see or can_edit"
        },
        {
          "package": "Yichus/Examples/Forum",
          "binding": "edit_post",
          "resource": "posts",
          "operation": "db_write",
          "kind": "GuardProven",
          "status": "holds",
          "detail": "dominated by can_see(Principal.user_id, row of threads) and can_edit(Principal.user_id, row of posts), on the row it was applied to (key thread_id)"
        }
      ],
      "resources": [
        {
          "resource": "profiles",
          "policy": "OwnerScoped",
          "status": "holds",
          "proven": true,
          "findings": [
            {
              "package": "Yichus/Examples/Forum",
              "binding": "get_profile",
              "resource": "profiles",
              "operation": "db_read_opt",
              "kind": "OwnerKeyProven",
              "status": "holds",
              "detail": "key derives from the authenticated Principal (user_id or owner_key)"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "put_profile",
              "resource": "profiles",
              "operation": "db_write",
              "kind": "OwnerKeyProven",
              "status": "holds",
              "detail": "key derives from the authenticated Principal (user_id or owner_key)"
            }
          ]
        },
        {
          "resource": "threads",
          "policy": "Guarded(can_see)",
          "status": "holds",
          "proven": true,
          "findings": [
            {
              "package": "Yichus/Examples/Forum",
              "binding": "open_thread",
              "resource": "threads",
              "operation": "db_next_id",
              "kind": "GuardedCreate",
              "status": "holds",
              "detail": "db_next_id on \"threads\" touches no existing row"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "open_thread",
              "resource": "threads",
              "operation": "db_write",
              "kind": "GuardedCreate",
              "status": "holds",
              "detail": "key is a fresh id from db_next_id on \"threads\": a create"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "list_threads",
              "resource": "threads",
              "operation": "db_query",
              "kind": "GuardedRead",
              "status": "holds",
              "detail": "rows of \"threads\" are tainted from here; every use must sit under can_see"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "list_threads",
              "resource": "threads",
              "operation": "keep_visible",
              "kind": "GuardProven",
              "status": "holds",
              "detail": "rows of \"threads\" filtered by can_see(Principal.user_id, row of threads)"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "read_thread",
              "resource": "threads",
              "operation": "db_read_opt",
              "kind": "GuardedRead",
              "status": "holds",
              "detail": "rows of \"threads\" are tainted from here; every use must sit under can_see"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "post_reply",
              "resource": "threads",
              "operation": "db_read_opt",
              "kind": "GuardedRead",
              "status": "holds",
              "detail": "rows of \"threads\" are tainted from here; every use must sit under can_see"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "edit_post",
              "resource": "threads",
              "operation": "db_read_opt",
              "kind": "GuardedRead",
              "status": "holds",
              "detail": "rows of \"threads\" are tainted from here; every use must sit under can_see"
            }
          ]
        },
        {
          "resource": "posts",
          "policy": "Guarded(can_see, can_edit)",
          "status": "holds",
          "proven": true,
          "findings": [
            {
              "package": "Yichus/Examples/Forum",
              "binding": "read_thread",
              "resource": "posts",
              "operation": "db_read",
              "kind": "GuardedRead",
              "status": "holds",
              "detail": "rows of \"posts\" are tainted from here; every use must sit under can_see or can_edit"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "post_reply",
              "resource": "posts",
              "operation": "db_read",
              "kind": "GuardedRead",
              "status": "holds",
              "detail": "rows of \"posts\" are tainted from here; every use must sit under can_see or can_edit"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "post_reply",
              "resource": "posts",
              "operation": "db_next_id",
              "kind": "GuardedCreate",
              "status": "holds",
              "detail": "db_next_id on \"posts\" touches no existing row"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "post_reply",
              "resource": "posts",
              "operation": "db_write",
              "kind": "GuardProven",
              "status": "holds",
              "detail": "dominated by can_see(Principal.user_id, row of threads), on the row it was applied to (key thread_id)"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "edit_post",
              "resource": "posts",
              "operation": "db_read",
              "kind": "GuardedRead",
              "status": "holds",
              "detail": "rows of \"posts\" are tainted from here; every use must sit under can_see or can_edit"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "edit_post",
              "resource": "posts",
              "operation": "db_write",
              "kind": "GuardProven",
              "status": "holds",
              "detail": "dominated by can_see(Principal.user_id, row of threads) and can_edit(Principal.user_id, row of posts), on the row it was applied to (key thread_id)"
            }
          ]
        },
        {
          "resource": "moderators",
          "policy": "Public",
          "status": "holds",
          "proven": true,
          "findings": [
            {
              "package": "Yichus/Examples/Forum",
              "binding": "grant_moderator",
              "resource": "moderators",
              "operation": "db_read",
              "kind": "PublicResource",
              "status": "holds",
              "detail": "resource \"moderators\" is Public; no key discipline required"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "grant_moderator",
              "resource": "moderators",
              "operation": "db_write",
              "kind": "PublicResource",
              "status": "holds",
              "detail": "resource \"moderators\" is Public; no key discipline required"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "grant_moderator",
              "resource": "moderators",
              "operation": "db_write",
              "kind": "PublicResource",
              "status": "holds",
              "detail": "resource \"moderators\" is Public; no key discipline required"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "list_threads",
              "resource": "moderators",
              "operation": "db_read",
              "kind": "PublicResource",
              "status": "holds",
              "detail": "resource \"moderators\" is Public; no key discipline required"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "read_thread",
              "resource": "moderators",
              "operation": "db_read",
              "kind": "PublicResource",
              "status": "holds",
              "detail": "resource \"moderators\" is Public; no key discipline required"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "post_reply",
              "resource": "moderators",
              "operation": "db_read",
              "kind": "PublicResource",
              "status": "holds",
              "detail": "resource \"moderators\" is Public; no key discipline required"
            },
            {
              "package": "Yichus/Examples/Forum",
              "binding": "edit_post",
              "resource": "moderators",
              "operation": "db_read",
              "kind": "PublicResource",
              "status": "holds",
              "detail": "resource \"moderators\" is Public; no key discipline required"
            }
          ]
        }
      ]
    },
    "organizationNames": {
      "status": "available",
      "entries": [
        {
          "declaration": "Yichus/Examples/Forum::forum_shape",
          "kind": "FamilySpec",
          "written": "get_profile",
          "resolvedId": "Yichus/Examples/Forum::get_profile",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:330:15"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_shape",
          "kind": "FamilySpec",
          "written": "put_profile",
          "resolvedId": "Yichus/Examples/Forum::put_profile",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:330:15"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_shape",
          "kind": "FamilySpec",
          "written": "grant_moderator",
          "resolvedId": "Yichus/Examples/Forum::grant_moderator",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:330:15"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_shape",
          "kind": "FamilySpec",
          "written": "open_thread",
          "resolvedId": "Yichus/Examples/Forum::open_thread",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:330:15"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_shape",
          "kind": "FamilySpec",
          "written": "list_threads",
          "resolvedId": "Yichus/Examples/Forum::list_threads",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:330:15"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_shape",
          "kind": "FamilySpec",
          "written": "read_thread",
          "resolvedId": "Yichus/Examples/Forum::read_thread",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:330:15"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_shape",
          "kind": "FamilySpec",
          "written": "post_reply",
          "resolvedId": "Yichus/Examples/Forum::post_reply",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:330:15"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_shape",
          "kind": "FamilySpec",
          "written": "edit_post",
          "resolvedId": "Yichus/Examples/Forum::edit_post",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:330:15"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_tables",
          "kind": "FamilySpec",
          "written": "profiles_table",
          "resolvedId": "Yichus/Examples/Forum::profiles_table",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:326:16"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_tables",
          "kind": "FamilySpec",
          "written": "threads_table",
          "resolvedId": "Yichus/Examples/Forum::threads_table",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:326:16"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_tables",
          "kind": "FamilySpec",
          "written": "posts_table",
          "resolvedId": "Yichus/Examples/Forum::posts_table",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:326:16"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_tables",
          "kind": "FamilySpec",
          "written": "moderators_table",
          "resolvedId": "Yichus/Examples/Forum::moderators_table",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:326:16"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "quote",
          "resolvedId": "Yichus/Examples/Forum::quote",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "join_with",
          "resolvedId": "Yichus/Examples/Forum::join_with",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "jraw",
          "resolvedId": "Yichus/Examples/Forum::jraw",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "jstr",
          "resolvedId": "Yichus/Examples/Forum::jstr",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "jobj",
          "resolvedId": "Yichus/Examples/Forum::jobj",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "jarr",
          "resolvedId": "Yichus/Examples/Forum::jarr",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "threads_table",
          "resolvedId": "Yichus/Examples/Forum::threads_table",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "posts_table",
          "resolvedId": "Yichus/Examples/Forum::posts_table",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "moderators_table",
          "resolvedId": "Yichus/Examples/Forum::moderators_table",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "profiles_table",
          "resolvedId": "Yichus/Examples/Forum::profiles_table",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "is_moderator",
          "resolvedId": "Yichus/Examples/Forum::is_moderator",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "can_see",
          "resolvedId": "Yichus/Examples/Forum::can_see",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "can_edit",
          "resolvedId": "Yichus/Examples/Forum::can_edit",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "respond",
          "resolvedId": "Yichus/Examples/Forum::respond",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "forbid",
          "resolvedId": "Yichus/Examples/Forum::forbid",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "not_found",
          "resolvedId": "Yichus/Examples/Forum::not_found",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "flag_if",
          "resolvedId": "Yichus/Examples/Forum::flag_if",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "check_text",
          "resolvedId": "Yichus/Examples/Forum::check_text",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "reject",
          "resolvedId": "Yichus/Examples/Forum::reject",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "render_thread",
          "resolvedId": "Yichus/Examples/Forum::render_thread",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "render_post",
          "resolvedId": "Yichus/Examples/Forum::render_post",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "has_room",
          "resolvedId": "Yichus/Examples/Forum::has_room",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "get_profile",
          "resolvedId": "Yichus/Examples/Forum::get_profile",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "put_profile",
          "resolvedId": "Yichus/Examples/Forum::put_profile",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "grant_moderator",
          "resolvedId": "Yichus/Examples/Forum::grant_moderator",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "list_threads",
          "resolvedId": "Yichus/Examples/Forum::list_threads",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "read_thread",
          "resolvedId": "Yichus/Examples/Forum::read_thread",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "post_reply",
          "resolvedId": "Yichus/Examples/Forum::post_reply",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "edit_post",
          "resolvedId": "Yichus/Examples/Forum::edit_post",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "thread_request_issues",
          "resolvedId": "Yichus/Examples/Forum::thread_request_issues",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "parse_thread",
          "resolvedId": "Yichus/Examples/Forum::parse_thread",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "open_thread",
          "resolvedId": "Yichus/Examples/Forum::open_thread",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        },
        {
          "declaration": "Yichus/Examples/Forum::forum_reading",
          "kind": "ReadingOrder",
          "written": "forum_api",
          "resolvedId": "Yichus/Examples/Forum::forum_api",
          "resolvedPackage": "Yichus/Examples/Forum",
          "location": "forum:335:17"
        }
      ],
      "scope": "FamilySpec members and ReadingOrder step targets. Names resolve by exact qualified identity, then local bare name, then a program-wide unique bare name. Ambiguity is refused. Resolution identifies ownership; it does not prove the authored description."
    },
    "roles": [
      {
        "id": "representation",
        "label": "Representation",
        "references": [
          "Yichus/Examples/Forum::respond",
          "Yichus/Examples/Forum::render_thread",
          "Yichus/Examples/Forum::render_post",
          "Yichus/Examples/Forum::jraw",
          "Yichus/Examples/Forum::jint",
          "Yichus/Examples/Forum::jarr"
        ]
      },
      {
        "id": "decisions",
        "label": "Decisions",
        "references": [
          "Yichus/Examples/Forum::can_see",
          "Yichus/Examples/Forum::can_edit",
          "Yichus/Examples/Forum::has_room",
          "Yichus/Examples/Forum::check_text"
        ]
      },
      {
        "id": "storage",
        "label": "Table handles",
        "references": [
          "Yichus/Examples/Forum::threads_table",
          "Yichus/Examples/Forum::posts_table",
          "Yichus/Examples/Forum::moderators_table"
        ]
      }
    ],
    "cells": {
      "Yichus/Examples/Forum::read_thread": {
        "representation": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::jarr",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19306,
                  "end": 19310,
                  "label": "forum:489:25",
                  "source": "jarr"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::jint",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19241,
                  "end": 19245,
                  "label": "forum:488:11",
                  "source": "jint"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::jraw",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19192,
                  "end": 19196,
                  "label": "forum:487:11",
                  "source": "jraw"
                },
                {
                  "file": "forum",
                  "start": 19292,
                  "end": 19296,
                  "label": "forum:489:11",
                  "source": "jraw"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::render_post",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19327,
                  "end": 19338,
                  "label": "forum:489:46",
                  "source": "render_post"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::render_thread",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19207,
                  "end": 19220,
                  "label": "forum:487:26",
                  "source": "render_thread"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::respond",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19162,
                  "end": 19169,
                  "label": "forum:486:14",
                  "source": "respond"
                }
              ]
            }
          ]
        },
        "decisions": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::can_see",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19056,
                  "end": 19063,
                  "label": "forum:484:10",
                  "source": "can_see"
                }
              ]
            }
          ]
        },
        "storage": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::moderators_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 18874,
                  "end": 18890,
                  "label": "forum:479:30",
                  "source": "moderators_table"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::posts_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19120,
                  "end": 19131,
                  "label": "forum:485:35",
                  "source": "posts_table"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::read_thread",
              "to": "Yichus/Examples/Forum::threads_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 18939,
                  "end": 18952,
                  "label": "forum:480:31",
                  "source": "threads_table"
                }
              ]
            }
          ]
        }
      },
      "Yichus/Examples/Forum::post_reply": {
        "representation": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::jarr",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20438,
                  "end": 20442,
                  "label": "forum:513:31",
                  "source": "jarr"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::jint",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20366,
                  "end": 20370,
                  "label": "forum:512:17",
                  "source": "jint"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::jraw",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20311,
                  "end": 20315,
                  "label": "forum:511:17",
                  "source": "jraw"
                },
                {
                  "file": "forum",
                  "start": 20424,
                  "end": 20428,
                  "label": "forum:513:17",
                  "source": "jraw"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::render_post",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20460,
                  "end": 20471,
                  "label": "forum:513:53",
                  "source": "render_post"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::render_thread",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20326,
                  "end": 20339,
                  "label": "forum:511:32",
                  "source": "render_thread"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::respond",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20275,
                  "end": 20282,
                  "label": "forum:510:20",
                  "source": "respond"
                }
              ]
            }
          ]
        },
        "decisions": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::can_see",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19913,
                  "end": 19920,
                  "label": "forum:504:14",
                  "source": "can_see"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::check_text",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19580,
                  "end": 19590,
                  "label": "forum:496:9",
                  "source": "check_text"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::has_room",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20025,
                  "end": 20033,
                  "label": "forum:506:16",
                  "source": "has_room"
                }
              ]
            }
          ]
        },
        "storage": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::moderators_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19711,
                  "end": 19727,
                  "label": "forum:499:34",
                  "source": "moderators_table"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::posts_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19981,
                  "end": 19992,
                  "label": "forum:505:39",
                  "source": "posts_table"
                },
                {
                  "file": "forum",
                  "start": 20096,
                  "end": 20107,
                  "label": "forum:507:47",
                  "source": "posts_table"
                },
                {
                  "file": "forum",
                  "start": 20156,
                  "end": 20167,
                  "label": "forum:508:43",
                  "source": "posts_table"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::post_reply",
              "to": "Yichus/Examples/Forum::threads_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 19780,
                  "end": 19793,
                  "label": "forum:500:35",
                  "source": "threads_table"
                }
              ]
            }
          ]
        }
      },
      "Yichus/Examples/Forum::edit_post": {
        "representation": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::jarr",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21858,
                  "end": 21862,
                  "label": "forum:541:35",
                  "source": "jarr"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::jint",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21782,
                  "end": 21786,
                  "label": "forum:540:21",
                  "source": "jint"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::jraw",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21723,
                  "end": 21727,
                  "label": "forum:539:21",
                  "source": "jraw"
                },
                {
                  "file": "forum",
                  "start": 21844,
                  "end": 21848,
                  "label": "forum:541:21",
                  "source": "jraw"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::render_post",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21880,
                  "end": 21891,
                  "label": "forum:541:57",
                  "source": "render_post"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::render_thread",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21738,
                  "end": 21751,
                  "label": "forum:539:36",
                  "source": "render_thread"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::respond",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21683,
                  "end": 21690,
                  "label": "forum:538:24",
                  "source": "respond"
                }
              ]
            }
          ]
        },
        "decisions": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::can_edit",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21419,
                  "end": 21427,
                  "label": "forum:534:20",
                  "source": "can_edit"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::can_see",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21178,
                  "end": 21185,
                  "label": "forum:529:14",
                  "source": "can_see"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::check_text",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20845,
                  "end": 20855,
                  "label": "forum:521:9",
                  "source": "check_text"
                }
              ]
            }
          ]
        },
        "storage": {
          "status": "observed",
          "witnesses": [
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::moderators_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 20976,
                  "end": 20992,
                  "label": "forum:524:34",
                  "source": "moderators_table"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::posts_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21246,
                  "end": 21257,
                  "label": "forum:530:39",
                  "source": "posts_table"
                },
                {
                  "file": "forum",
                  "start": 21544,
                  "end": 21555,
                  "label": "forum:536:47",
                  "source": "posts_table"
                }
              ]
            },
            {
              "from": "Yichus/Examples/Forum::edit_post",
              "to": "Yichus/Examples/Forum::threads_table",
              "kind": "user-reference",
              "locations": [
                {
                  "file": "forum",
                  "start": 21045,
                  "end": 21058,
                  "label": "forum:525:35",
                  "source": "threads_table"
                }
              ]
            }
          ]
        }
      }
    },
    "scope": "All user-binding references, including self references, in this compiled snapshot. References may pass functions as values; they do not assert execution. Role cells cover only their explicitly listed targets. Effects are recognized direct primitive sites, not a transitive execution trace. Locations may be unavailable after compilation. Groups and role meanings are authored; they do not prove encapsulation, coherence or policy correctness."
  }
}
