memhouse 0.17.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +109 -30
  2. package/bin/memhouse.js +555 -202
  3. package/editors/antigravity.js +2 -0
  4. package/editors/claude.js +3 -1
  5. package/editors/codebuff.js +2 -0
  6. package/editors/codex.js +4 -1
  7. package/editors/commandcode.js +2 -1
  8. package/editors/copilot-jetbrains.js +2 -1
  9. package/editors/copilot.js +2 -1
  10. package/editors/cursor-agent.js +2 -1
  11. package/editors/cursor.js +2 -0
  12. package/editors/gemini.js +2 -1
  13. package/editors/goose.js +2 -1
  14. package/editors/index.js +8 -1
  15. package/editors/kiro.js +3 -2
  16. package/editors/opencode.js +2 -1
  17. package/editors/scope.js +126 -0
  18. package/editors/vscode.js +2 -0
  19. package/editors/zed.js +2 -1
  20. package/memhouse/DESIGN.md +31 -8
  21. package/memhouse/binding.js +81 -0
  22. package/memhouse/channel.js +50 -0
  23. package/memhouse/delivery/AGENT-INSTALL-PROMPT.md +2 -1
  24. package/memhouse/delivery/AGENT-INSTALL.md +1 -1
  25. package/memhouse/delivery/INVITATION.md.tpl +147 -0
  26. package/memhouse/delivery/PROMPT.md +6 -5
  27. package/memhouse/delivery/kernel-install.md +4 -2
  28. package/memhouse/delivery/plugin/.claude-plugin/plugin.json +1 -1
  29. package/memhouse/delivery/plugin/reference/HOUSE.md +38 -12
  30. package/memhouse/delivery/plugin/skills/access/SKILL.md +9 -9
  31. package/memhouse/delivery/plugin/skills/admin/SKILL.md +1 -1
  32. package/memhouse/delivery/plugin/skills/house/SKILL.md +18 -2
  33. package/memhouse/flags.js +5 -4
  34. package/memhouse/house/HOUSE.md +25 -11
  35. package/memhouse/house/house.js +110 -27
  36. package/memhouse/house/migrate.js +7 -6
  37. package/memhouse/house/relocate.js +2 -2
  38. package/memhouse/house/schema.sql.tpl +3 -3
  39. package/memhouse/invitefile.js +38 -0
  40. package/memhouse/provision.js +100 -0
  41. package/memhouse/shipper/ship.js +87 -28
  42. package/package.json +1 -1
@@ -0,0 +1,147 @@
1
+ # You have been invited to a memhouse
2
+
3
+ {{INVITER}} set up a **house** — a ClickHouse database where a team keeps its coding-agent
4
+ memory — and made you a member of it. This page walks you from the file you were sent to a
5
+ working install, and shows what you get.
6
+
7
+ You received two things:
8
+
9
+ | file | what it is |
10
+ |---|---|
11
+ | `{{FILE}}` | **your credential**, in this same folder. One-time: install consumes it and deletes it. Treat it like a password until then. |
12
+ | this page | the steps. Nothing secret in here. |
13
+
14
+ Do it yourself, or hand this page to your coding agent. From the directory holding both
15
+ files:
16
+
17
+ ```
18
+ claude "Read MEMHOUSE-INVITATION.md and follow it. Ask me before each step that changes this machine."
19
+ ```
20
+
21
+ Any agent that can run shell commands works the same way; the rules it must keep are at
22
+ the end of this page.
23
+
24
+ ## 0. Find your credential
25
+
26
+ The install needs `{{FILE}}`, which was sent alongside this page. Confirm it is here first —
27
+ run this from the same directory, and if it prints the filename you are ready:
28
+
29
+ ```
30
+ ls invite-*.env
31
+ ```
32
+
33
+ If it is missing, it did not travel with this page; get it from whoever invited you before
34
+ going on. Do not print its contents — the last line of it is a password.
35
+
36
+ ## 1. Install memhouse
37
+
38
+ {{INSTALL}}
39
+
40
+ On most Linux distros the global install needs `sudo`; if `npm` says `EACCES`, that is why.
41
+ `memhouse --version` should print `{{VERSION}}`.
42
+
43
+ ## 2. Join the house
44
+
45
+ From the directory holding `{{FILE}}`, just run memhouse — it finds the invitation and asks:
46
+
47
+ ```
48
+ memhouse
49
+ ```
50
+
51
+ (or, without the question: `memhouse install --env {{FILE}}`)
52
+
53
+ What that does, in order: connects to `{{URL}}` as `{{NAME}}`, **rotates your password to
54
+ one only your machine knows**, creates your rooms, writes your config to `~/.memhouse/env`,
55
+ deletes `{{FILE}}`, and starts shipping in the background. The password in the file stops
56
+ working the moment install finishes, so a copy left in a chat is dead.
57
+
58
+ ## 3. Check it is working
59
+
60
+ ```
61
+ memhouse status # your rooms, how much is in them, the shipper's pulse
62
+ memhouse doctor # every line a check mark = healthy
63
+ memhouse discover # what this machine ships, and where each editor's sessions were found
64
+ ```
65
+
66
+ `memhouse status` shows a session count that grows for a few minutes on a machine with
67
+ history; the first pass ships everything you have. After that it ships new turns as they
68
+ happen.
69
+
70
+ ## 4. What you own, and who can see it
71
+
72
+ Your memory lives in five tables named for you inside `{{DB}}` — `{{DB}}.{{NAME}}_messages`,
73
+ `{{DB}}.{{NAME}}_sessions`, `{{DB}}.{{NAME}}_tool_calls` and two bookkeeping tables — and you
74
+ hold exactly one grant, on `{{DB}}.{{NAME}}_*`. Housemates cannot read your rooms, list
75
+ them, or grant them to anyone; you cannot read theirs. `memhouse whoami --json` reads that
76
+ grant back from the server. What can always see everything is the account that administers
77
+ the ClickHouse, which is {{INVITER}}'s — the same as any database you use at work.
78
+
79
+ Everything your editors write to disk ships verbatim: prompts, replies, tool calls and their
80
+ arguments, including anything an agent ever pasted into a session. The house is as
81
+ sensitive as your shell history. If some of your work should not go there, say so before
82
+ shipping — see "which sessions ship" below.
83
+
84
+ ## 5. Things to try
85
+
86
+ ```
87
+ memhouse search "the error you fixed last week"
88
+ memhouse resume <session-id> # prints the command that reopens that session
89
+ memhouse plugins install claude # /mem:recall, /mem:sql, /mem:house, /mem:access, /mem:admin
90
+ ```
91
+
92
+ Then, inside Claude Code:
93
+
94
+ ```
95
+ /mem:recall how did I set up the ClickHouse tunnel
96
+ /mem:sql what did I spend on Opus this month
97
+ /mem:house
98
+ ```
99
+
100
+ Sharing is yours to give and take back, no operator involved:
101
+
102
+ ```
103
+ memhouse share <housemate> everything you own
104
+ memhouse share <housemate> --only project=<name> one project
105
+ memhouse share --list
106
+ memhouse share <housemate> --revoke
107
+ ```
108
+
109
+ ## Which sessions ship
110
+
111
+ Everything memhouse finds on the machine — every supported editor, every Claude Code
112
+ config directory. `memhouse discover` lists what it found and the variable that narrows
113
+ each one. Two lines in `~/.memhouse/env` are the common case:
114
+
115
+ ```
116
+ MEMHOUSE_EDITORS='claude'
117
+ MEMHOUSE_CLAUDE_ROOTS='~/.claude-playbooks/<the one instance you mean>'
118
+ ```
119
+
120
+ ## If something refuses
121
+
122
+ Every refusal says what to do next. The two you might meet: `EACCES` on install means
123
+ `sudo`, and `needed rights this credential does not hold` means the grant on the server is
124
+ narrower than the one memhouse issues — ask {{INVITER}} to run `memhouse install --print-sql
125
+ --member {{NAME}}` and apply what it prints.
126
+
127
+ ## For an agent following this page
128
+
129
+ You are installing memhouse for the person who handed you this file. Five rules; three of
130
+ them exist because an agent broke them:
131
+
132
+ 0. **Your credential is `{{FILE}}` in the directory this page is in.** If `Read
133
+ MEMHOUSE-INVITATION.md` is all you were given, `ls invite-*.env` beside it is the file
134
+ the steps refer to; confirm it is there before step 1.
135
+ 1. **Never print `{{FILE}}` or any `MEMHOUSE_*` value.** No `cat`, no `echo $MEMHOUSE_PASSWORD`,
136
+ no `set -x`. This very session will be shipped into the house; a password printed here is
137
+ a password archived.
138
+ 2. **Run the commands as written, in order.** Do not substitute `CREATE USER`, `GRANT` or any
139
+ SQL of your own; there is nothing to fix on the server from this side.
140
+ 3. **Ask before `memhouse install --env`.** It rotates the credential, deletes `{{FILE}}`,
141
+ and starts shipping this machine's transcripts. The person decides when that happens.
142
+ 4. **A ✗ line is the end of that step, not an invitation to work around it.** Read the line
143
+ after it — every refusal names its remedy — do that or report it. `sudo` for `EACCES` is
144
+ the one you may apply yourself.
145
+ 5. **Report what `memhouse status` and `memhouse doctor` say**, verbatim, when you are done.
146
+ A green install is those two commands, not your summary of them.
147
+
@@ -36,11 +36,12 @@ FIRST. Only say you don't know after a search comes back empty.
36
36
 
37
37
  Without skills, query directly.
38
38
 
39
- **Table names.** The house's rooms are three plain, shared tables — `messages`,
40
- `sessions`, `tool_calls` — in the connection's database. Everyone in the house writes
41
- into the same tables; `user_id` (server-stamped) says whose row it is and `host` says
42
- which machine. Query the whole house by default; add `WHERE user_id = '<name>'` for one
43
- person. **There is no `sessions_v` object** — the rollup is a saved query, and
39
+ **Table names.** The rooms are `messages`, `sessions`, `tool_calls` in the connection's
40
+ database — unless this is a shared house, where they carry the member's own prefix
41
+ (`alice_messages`). `memhouse rooms` prints what yours are actually called; a bare
42
+ `FROM messages` is not a table you have in a shared house. `user_id` (server-stamped)
43
+ says whose row it is and `host` says which machine. To read across several members, UNION ALL over the rooms you hold — naming a room
44
+ you do not hold is an error rather than a silent omission. **There is no `sessions_v` object** — the rollup is a saved query, and
44
45
  `memhouse sessions-query` prints it ready to drop into a `FROM (...) AS c`.
45
46
 
46
47
  **One session can be stored more than once.** The shipper never deletes: when an editor
@@ -80,8 +80,10 @@ user so the stamp cannot be skipped). Her machines are told apart by `host`.
80
80
  **A house is shared by its housemates.** The tables are common; `user_id` and `host` say
81
81
  who wrote what, and `WHERE user_id = 'alice'` is one person. The boundary is the
82
82
  DATABASE: a member of `mem` holds nothing on any other database, so two agencies on one
83
- kernel ClickHouse cannot read each other. The model is collaborative — housemates trust
84
- each other with the house; a separate house is the isolation mechanism.
83
+ kernel ClickHouse cannot read each other. WITHIN a house, members hold their own rooms
84
+ and nothing else — housemates are isolated from each other by grant, not by trust, and
85
+ each can verify it with `SHOW GRANTS`. A separate house remains the boundary between
86
+ groups that should not know of each other at all.
85
87
 
86
88
  Row policies are still the only way to share a *subset* of rows, which is owner-mediated
87
89
  and documented in `SHARING.md` — they are not how isolation works.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mem",
3
3
  "description": "Conversation memory for AI agents over the memhouse typed ClickHouse store: recall past sessions and answer from them, run analytics, check the house, bring people in, and administer the server. Skills install as /mem:recall, /mem:sql, /mem:house, /mem:access, and /mem:admin.",
4
- "version": "0.17.0",
4
+ "version": "0.18.1",
5
5
  "author": {
6
6
  "name": "Ramazan Polat"
7
7
  },
@@ -8,13 +8,20 @@ or wrong everywhere.
8
8
 
9
9
  ## What this is
10
10
 
11
- A **house** is a ClickHouse **database**. Its **rooms** are three shared tables:
12
- `sessions`, `messages`, `tool_calls`. Everyone granted on the database writes into the
13
- same tables; the server stamps who. There is no per-user table and no cloud — the
14
- database *is* the boundary, and a house's grants reach nothing outside it.
11
+ A **house** is a ClickHouse **database** — on the user's machine, their server, or a
12
+ hosted ClickHouse; memhouse runs no service of its own. Its **rooms** are tables —
13
+ `sessions`, `messages`, `tool_calls` — and the server stamps who wrote every row. A
14
+ house's grants reach nothing outside it.
15
15
 
16
- A **member** owns one house. An **administrator** owns the ClickHouse. `memhouse whoami`
17
- says which you are holding.
16
+ Every member's rooms are named for them — `mem.alice_messages`, `mem.alice_sessions`,
17
+ `mem.alice_tool_calls` — and one grant covers exactly those: `ON mem.alice_*`. Housemates
18
+ keep their own rooms beside yours and cannot read them, list them, or grant them onward;
19
+ you cannot read theirs. `SHOW GRANTS` shows you the one line you hold. **A bare
20
+ `FROM messages` names nothing you have** — the `q()` below prefixes room names with your
21
+ member name for you, and `memhouse rooms` prints what yours are called.
22
+
23
+ An **operator** owns the ClickHouse itself; an **admin credential** is what proves it.
24
+ `memhouse whoami` says which you are holding.
18
25
 
19
26
  Rows arrive from a **shipper** that parses local transcripts from 17 editors. It only
20
27
  ever inserts. Nothing in memhouse runs an LLM over your data — these skills retrieve
@@ -29,6 +36,13 @@ rows, and *you* read them.
29
36
  memhouse ships back into the house — the archive is insert-only, so a leaked credential
30
37
  cannot be withdrawn.
31
38
 
39
+ **Which memhouse.** `plugins install` stamps two variables into this config directory's
40
+ `settings.json`, so every session here carries them: `MEMHOUSE_HOME` is the instance whose
41
+ house these skills read, and `MEMHOUSE_BIN` is that instance's binary. **Every `memhouse …`
42
+ command in these skills means `"${MEMHOUSE_BIN:-memhouse}"`.** A machine can run two
43
+ instances on two channels; the bare name would be whichever the shell found first. Do not
44
+ override either variable.
45
+
32
46
  Credentials resolve **flags > exported `MEMHOUSE_*` > `$MEMHOUSE_HOME/env`** (default
33
47
  `~/.memhouse/env`) — the same order the CLI uses. The dance below snapshots the
34
48
  environment first, because sourcing the file would otherwise clobber an already-exported
@@ -45,7 +59,8 @@ if [ -z "${MEMHOUSE_URL:-}" ] || [ -z "${MEMHOUSE_USER:-}" ]; then
45
59
  fi
46
60
 
47
61
  q() { # read-only by construction; every read path should use this
48
- curl -sS --fail-with-body --user "$MEMHOUSE_USER:${MEMHOUSE_PASSWORD:-}" \
62
+ sed -E "s/([[:space:](]|^)(FROM|JOIN)[[:space:]]+(sessions|messages|tool_calls|meta|events)([[:space:];,)]|\$)/\1\2 ${MEMHOUSE_USER}_\3\4/g" \
63
+ | curl -sS --fail-with-body --user "$MEMHOUSE_USER:${MEMHOUSE_PASSWORD:-}" \
49
64
  --data-binary @- "$MEMHOUSE_URL/?database=${MEMHOUSE_DB:-$MEMHOUSE_USER}&readonly=1"
50
65
  }
51
66
  q <<'SQL'
@@ -56,11 +71,22 @@ SQL
56
71
  `readonly=1` is a ClickHouse-side setting: even a mis-generated `DROP` is refused by the
57
72
  server, not by discipline.
58
73
 
59
- **Reading someone else's house.** A share is a read-only `GRANT SELECT` on their
60
- database. `SHOW DATABASES` lists what your credential may read; anything that is not
61
- `system`, `information_schema`, `default` or your own `$MEMHOUSE_DB` was shared with you.
62
- To read it, change `database=` in the URL and leave the table names bare. Say whose house
63
- an answer came from.
74
+ **The `sed` is what makes every query below work in both layouts** — write room names
75
+ bare and it supplies the prefix when there is one. It rewrites only after `FROM`/`JOIN`,
76
+ so a needle like `LIKE '%messages%'` is untouched, and `FROM yigit_messages` is left
77
+ alone — the room name must follow whitespace, and there is none inside `yigit_messages`.
78
+ With no prefix set it expands to nothing and the query passes through verbatim.
79
+
80
+ It is spelled with `[[:space:]]` classes rather than `\b` because **BSD `sed` does not
81
+ support `\b`**: on macOS the `\b` form matched nothing and sent the query through
82
+ unprefixed. That fails loudly as `UNKNOWN_TABLE` rather than quietly reading wrong rows,
83
+ which is the right way round — but it fails.
84
+
85
+ **Reading a housemate's memory.** A share is `GRANT SELECT ON mem.<them>_*` — their
86
+ rooms, not the database. `SHOW TABLES` lists exactly what you may read: your own rooms plus
87
+ any shared with you. Name a housemate's rooms in full (`FROM yigit_messages`); the `q()`
88
+ rewrite leaves an already-prefixed name alone, since applying yours would point at the
89
+ wrong rooms. Say whose memory an answer came from.
64
90
 
65
91
  ---
66
92
 
@@ -26,7 +26,7 @@ This runs the `memhouse invite` CLI and nothing else. **Do not hand-run `CREATE
26
26
  `GRANT` with an admin password substituted into a command** — that burns the credential
27
27
  into a transcript on disk. The CLI passes it to one process and never echoes it.
28
28
 
29
- 1. **Check the binary:** `command -v memhouse`. Absent → tell the user to
29
+ 1. **Check the binary:** `command -v "${MEMHOUSE_BIN:-memhouse}"`. Absent → tell the user to
30
30
  `npm install -g memhouse`. There is no in-skill fallback, on purpose.
31
31
 
32
32
  2. **Gather only two things:** the invitee's **name** (validate `[A-Za-z][A-Za-z0-9_]*`;
@@ -84,13 +84,13 @@ into a transcript on disk. The CLI passes it to one process and never echoes it.
84
84
  5. **Say whether the house was fresh** — `SELECT count() FROM <db>.messages` reads 0 for a
85
85
  new one. Second line of defence behind step 3's refusal.
86
86
 
87
- 6. **Write the message the user will send.** They are handing over a file plus an
88
- explanation; compose it rather than making them. Cover: what memhouse is in a sentence
89
- or two; that the attached file IS a password (do not forward, do not paste in chat);
90
- `npm install -g memhouse` (Node 24+) then `memhouse install --env invite-<name>.env`;
91
- that install offers to change the password to one only they know and then deletes the
92
- file, so they should say yes; `memhouse onboard` to start shipping and `memhouse status`
93
- to check; and that their house is theirs alone unless they run `/mem:access share`.
87
+ 6. **Write the message the user will send.** `invite` wrote TWO files beside each other:
88
+ `invite-<name>.env` (the credential, one-time) and `MEMHOUSE-INVITATION.md` (the steps,
89
+ nothing secret — install, verify, what they own, things to try). The guide does the
90
+ explaining, so the message is short: what memhouse is in a sentence; that the `.env` IS a
91
+ password (do not forward, do not paste in chat); open `MEMHOUSE-INVITATION.md` and follow
92
+ it. If `memhouse --version` shows a pre-release (a `-` in it), the invitee also needs the
93
+ tarball this build came from (`memhouse nightly --out …`); the guide says so and names it.
94
94
 
95
95
  If they are REPLACING an existing credential, add `memhouse ship --full` — a plain
96
96
  incremental pass skips sessions the new house has no record of, so their history would
@@ -105,7 +105,7 @@ for this** — partial sharing has four ways to go wrong quietly, and the comman
105
105
  each one:
106
106
 
107
107
  ```
108
- memhouse share <user> the whole house
108
+ memhouse share <user> everything you own
109
109
  memhouse share <user> --only project=memhouse just one project
110
110
  memhouse share <user> --only session=<id> just one conversation
111
111
  memhouse share --list who can read it, and how much
@@ -8,7 +8,7 @@ allowed-tools: Bash
8
8
 
9
9
  # /mem:admin — operate the house as its administrator
10
10
 
11
- A member owns one database. An **administrator** owns the ClickHouse: every house, every
11
+ A member owns a house, or rooms in one. An **administrator** owns the ClickHouse: every house, every
12
12
  account, every grant. This skill is the second one, and it is the only skill allowed to
13
13
  act outside the caller's own house.
14
14
 
@@ -32,6 +32,22 @@ stop:
32
32
  > `memhouse deploy --local` stands one up bound to loopback. Someone invited you?
33
33
  > `memhouse install --env invite-<you>.env`.
34
34
 
35
+ ## First: which memhouse this is
36
+
37
+ Before anything else, run and show verbatim:
38
+
39
+ ```
40
+ "${MEMHOUSE_BIN:-memhouse}" instance
41
+ ```
42
+
43
+ One screen: the instance's name and home, the binary and channel, the house (server,
44
+ database, member, whether an admin credential is present), the five rooms with row counts,
45
+ what this machine ships, the host identity, the daemons, and which playbooks are bound to
46
+ this instance. A machine can run several instances on different channels; this is how the
47
+ user tells them apart, and how you know which house every answer below comes from. If the
48
+ instance shown is not the one the user meant, stop and say so — the fix is launching
49
+ under the right playbook, not overriding variables.
50
+
35
51
  ## The report
36
52
 
37
53
  Lead with the one-line verdict — *working and current*, *working but stale*, or *not
@@ -83,12 +99,12 @@ thin. Say what could not be seen rather than guessing.
83
99
  SHOW DATABASES
84
100
  -- who you have granted (memhouse's own record of it)
85
101
  SELECT substring(key, 7) AS user, value AS state
86
- FROM house_meta FINAL WHERE key LIKE 'share:%' ORDER BY key
102
+ FROM meta FINAL WHERE key LIKE 'share:%' ORDER BY key
87
103
  -- everyone on the server (names only — every member holds SHOW USERS)
88
104
  SELECT name FROM system.users ORDER BY name
89
105
  ```
90
106
 
91
- That `house_meta` list is memhouse's own note-keeping, not ClickHouse's grant table —
107
+ That `meta` list is memhouse's own note-keeping, not ClickHouse's grant table —
92
108
  a member cannot read `system.grants`. Present it as "what memhouse recorded", and say
93
109
  that a grant made by hand would not appear.
94
110
 
package/memhouse/flags.js CHANGED
@@ -16,16 +16,17 @@ const COMMAND_FLAGS = {
16
16
  null: [], help: [], version: [],
17
17
  whoami: ['admin'],
18
18
  share: ['only', 'revoke', 'list'],
19
- discover: [], stats: [], stop: [], doctor: [], 'sessions-query': [],
19
+ discover: [], stats: [], stop: [], doctor: [], 'sessions-query': [], rooms: [], instance: [], members: ['db','admin-user','admin-password'],
20
20
  status: [], start: [],
21
21
  onboard: ['url', 'user', 'password', 'db', 'port', 'no-ship', 'target', 'house-port', 'tag', 'local'],
22
22
  install: ['url', 'user', 'password', 'db', 'port', 'no-ship', 'env', 'print-sql', 'member',
23
- 'member-password', 'admin-user', 'admin-password', 'ensure-schema', 'rotate-password', 'force'],
24
- setup: ['url', 'user', 'password', 'db', 'port'],
23
+ 'member-password', 'admin-user', 'admin-password', 'ensure-schema', 'rotate-password', 'force',
24
+ 'editors', 'claude-roots', 'channel'],
25
+ setup: ['url', 'user', 'password', 'db', 'port', 'admin-user', 'admin-password', 'editors', 'claude-roots', 'channel'],
25
26
  ship: ['full', 'loop', 'ensure-schema'],
26
27
  search: ['limit'],
27
28
  resume: [],
28
- update: ['check', 'migrate', 'no-install'],
29
+ update: ['check', 'migrate', 'no-install', 'channel'],
29
30
  reset: ['all-origins'],
30
31
  invite: ['url', 'db', 'out', 'admin-user', 'admin-password', 'adopt', 'print-sql',
31
32
  'allow-local', 'member-password'],
@@ -1,12 +1,18 @@
1
- # The house — a database, three shared rooms
1
+ # The house — a database, and the rooms in it
2
2
 
3
3
  **A house is a ClickHouse database.** Any database, named whatever its people name it —
4
- `polat`, `team_a`, even `default`. Its rooms are three plain tables: `sessions`,
5
- `messages`, `tool_calls`. There is nothing else to provision: no per-member tables, no
6
- Merge rooms, no views, no settings profile.
4
+ `polat`, `team_a`, even `default`. Its rooms are tables: `sessions`, `messages`,
5
+ `tool_calls`. No views, no Merge rooms, no settings profile.
7
6
 
8
- **Everyone in the house writes into the same tables**, each with their own credential,
9
- and two columns say where every row came from:
7
+ **Every member's rooms are named for them, and one grant covers them.** `mem.polat_*`
8
+ for polat, `mem.alice_*` for alice, in the same database — `mem` unless somebody has a
9
+ reason. The grant is `GRANT … ON mem.polat_* TO polat WITH GRANT OPTION`: it lets the
10
+ member create and rebuild their own rooms, share them, and reach nothing else. Nobody is
11
+ granted the database itself. A house with one member is a house of one, not a different
12
+ kind of house — a colleague joins as one more member and nothing about the first changes.
13
+ `roomNames()` in `house.js` is the only place a table name is produced.
14
+
15
+ Two columns say where every row came from:
10
16
 
11
17
  | Column | Meaning | Comes from |
12
18
  |---|---|---|
@@ -31,9 +37,17 @@ shipper create and evolve the rooms (`ship.js --ensure-schema`) — no admin has
31
37
  memhouse code. Joining a ClickHouse that happens to run a kernel is the same three
32
38
  statements: a database and a credential, nothing else.
33
39
 
34
- The model is **collaborative**: housemates trust each other with the house. Narrower
35
- grants can be layered on later if a team wants them; the isolation mechanism between
36
- groups that do NOT trust each other is a separate house.
40
+ **Housemates do not have to trust each other with the house.** They used to: everyone
41
+ held `ALL` on the database, and the isolation mechanism between parties who should not
42
+ see each other was a separate house. That shape leaked — one member could `GRANT SELECT
43
+ ON db.* TO <outsider>` and hand over a housemate's transcripts, with no admin and no
44
+ notification.
45
+
46
+ In a shared house each member is granted their own rooms and nothing else, so isolation
47
+ lives INSIDE one house and is checkable: `SHOW GRANTS` lists what you hold, and `SHOW
48
+ TABLES` does not list what you do not. A separate house is still the boundary between
49
+ groups that should not even know of each other — names leak across a shared house even
50
+ when content does not.
37
51
 
38
52
  ## One user on two machines, same session id
39
53
 
@@ -91,9 +105,9 @@ for writes and DDL.
91
105
 
92
106
  Two tables that are not rooms:
93
107
 
94
- - `house_meta` — house-wide key/value, latest-wins: `schema_version`, and the memhouse
108
+ - `meta` — house-wide key/value, latest-wins: `schema_version`, and the memhouse
95
109
  version each member last shipped with.
96
- - `house_events` — append-only: migrations (`pending` → `applied` | `failed`), version
110
+ - `events` — append-only: migrations (`pending` → `applied` | `failed`), version
97
111
  changes, schema observations, each with actor, host and row counts. Nothing is updated
98
112
  in place, so a migration that failed and was retried reads as exactly that.
99
113