k0-board 0.5.0 → 0.6.0

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.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,70 @@ All notable changes to this project are documented here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.6.0]
10
+
11
+ k0 gets an account and a cloud. The board still runs on your machine and keeps working with no
12
+ network, but it now keeps a copy of itself in k0 Cloud, signs in with GitHub or Google, and numbers
13
+ every story once for your whole account instead of once per repository; a board that existed before
14
+ moves over once, after you have seen every old number beside its new one. k0 is in early access,
15
+ and from this version on it is source-available under the Sustainable Use License rather than MIT.
16
+
17
+ ### Added
18
+
19
+ - **k0 Cloud: your board keeps a copy of itself, and you sign in with GitHub or Google.** The board
20
+ still lives on your machine and works with no network at all; every few seconds it sends what
21
+ changed and fetches what your other machines changed, so it survives a lost laptop and reaches a
22
+ second one. Which terminal a session is in, the folder it works in and the commit it started at
23
+ never leave the machine, and nothing from your repositories goes up — not files, not commits.
24
+ k0 is in early access: once you are signed in the board says *You are on the list* and sends
25
+ nothing until your account has been approved, and it notices the approval by itself. The
26
+ sign-in screen only stands in front of the board when there is a way past it. A read-only board
27
+ on the web, and the page where accounts are approved, are coming with the site.
28
+ - **A key is one number for your whole account.** `K150` is the same story in every repository and
29
+ on every machine, and the number comes from the cloud the moment the story is made. Without a
30
+ connection the story is made anyway with a provisional key, `K~3`, which becomes a real one —
31
+ file in `.k0/` renamed with it — as soon as the cloud answers again. Without an account the same
32
+ single counter is kept on your machine.
33
+ - **Moving a board you already had to the account, once, when you say so.** The first time you
34
+ sign in on a machine whose board has stories, nothing is sent until the board has been moved:
35
+ the board shows every old key beside its new one, repository by repository, and how many plans,
36
+ prompts and decisions mention a key. On yes it keeps a copy of the whole board first, renumbers
37
+ everything in the order it was made, updates the keys written inside the text, renames the
38
+ files in `.k0/`, and leaves a list of every old key and its new one beside the copy. *Not now*
39
+ leaves the board exactly as it was.
40
+ - **Who is signed in, and whether the cloud has everything, at the end of the top bar.** Your
41
+ picture and a dot: green when everything is in the cloud, amber while changes are waiting, grey
42
+ when the cloud cannot be reached and the board is carrying on by itself. Its menu has *Sync now*
43
+ and *Sign out*.
44
+ - **`k0-board login` and `k0-board logout`**, and a *k0 Cloud* section in `k0-board doctor` saying
45
+ who is signed in, whether they have been let in, whether the board still has to be moved, and
46
+ how many changes are waiting.
47
+
48
+ How far this has been tried: the whole road was run against the real cloud with a throwaway
49
+ account — signing in, waiting to be let in, the move, a new story numbered by the cloud, and its
50
+ rows arriving there — and the move was rehearsed on a copy of a real board of 938 stories across
51
+ 25 repositories. Signing in with GitHub or Google for real has not been tried yet, because neither
52
+ is switched on in the cloud.
53
+
54
+ ### Changed
55
+
56
+ - **A story moved to another repository keeps its key.** It used to be given a new one from the
57
+ repository it moved to; now that a key is one number for the whole account, there is nothing
58
+ there for it to collide with.
59
+
60
+ - **k0 is now under the Sustainable Use License instead of MIT.** The code stays public, all of it,
61
+ and you can still use it, change it, and run it for yourself or inside your company; what the
62
+ license no longer allows is taking k0 and selling it to other people as a hosted service. It is
63
+ source-available, not open source, and k0 no longer calls itself that. Versions up to and
64
+ including 0.5.0 were released under MIT and remain under it. The manual and the security notes
65
+ also stop saying that k0 makes a single network request: it now has an account and a cloud of
66
+ its own, and they say so — two places, the cloud and the daily version check, and still nothing
67
+ else.
68
+
69
+ ### Fixed
70
+
71
+ - **The new tests pass on Windows too.** Nothing about k0 itself changed.
72
+
9
73
  ## [0.5.0]
10
74
 
11
75
  **The board tells you what to do next, and starts it.** Every story carries one button saying the
@@ -697,7 +761,8 @@ here is everything that had to change for it to be somebody else's tool as well.
697
761
  - The personal fixtures k0 grew up on. `test/clean.test.mjs` now fails the build if any of them
698
762
  come back.
699
763
 
700
- [Unreleased]: https://github.com/alessio-ragni/k0-board/compare/v0.5.0...HEAD
764
+ [Unreleased]: https://github.com/alessio-ragni/k0-board/compare/v0.6.0...HEAD
765
+ [0.6.0]: https://github.com/alessio-ragni/k0-board/compare/v0.5.0...v0.6.0
701
766
  [0.5.0]: https://github.com/alessio-ragni/k0-board/compare/v0.4.0...v0.5.0
702
767
  [0.4.0]: https://github.com/alessio-ragni/k0-board/compare/v0.3.0...v0.4.0
703
768
  [0.3.0]: https://github.com/alessio-ragni/k0-board/compare/v0.2.0...v0.3.0
package/LICENSE CHANGED
@@ -1,21 +1,86 @@
1
- MIT License
1
+ # License
2
+
3
+ Versions of k0 (the `k0-board` package) up to and including 0.5.0 were released under the MIT
4
+ License and remain available under it. Everything released after 0.5.0 is licensed as follows.
2
5
 
3
6
  Copyright (c) 2026 Alessio Ragni
4
7
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
8
+ The licensor is Alessio Ragni. The software is k0, published on npm as `k0-board`, together with
9
+ its source code at https://github.com/alessio-ragni/k0-board. All third party components
10
+ incorporated into the software are licensed under the original license provided by the owner of
11
+ the applicable component. Everything else is available under the Sustainable Use License as
12
+ defined below.
13
+
14
+ ## Sustainable Use License
15
+
16
+ Version 1.0
17
+
18
+ ### Acceptance
19
+
20
+ By using the software, you agree to all of the terms and conditions below.
21
+
22
+ ### Copyright License
23
+
24
+ The licensor grants you a non-exclusive, royalty-free, worldwide, non-sublicensable, non-transferable license
25
+ to use, copy, distribute, make available, and prepare derivative works of the software, in each case subject
26
+ to the limitations below.
27
+
28
+ ### Limitations
29
+
30
+ You may use or modify the software only for your own internal business purposes or for non-commercial or
31
+ personal use. You may distribute the software or provide it to others only if you do so free of charge for
32
+ non-commercial purposes. You may not alter, remove, or obscure any licensing, copyright, or other notices of
33
+ the licensor in the software. Any use of the licensor’s trademarks is subject to applicable law.
34
+
35
+ ### Patents
36
+
37
+ The licensor grants you a license, under any patent claims the licensor can license, or becomes able to
38
+ license, to make, have made, use, sell, offer for sale, import and have imported the software, in each case
39
+ subject to the limitations and conditions in this license. This license does not cover any patent claims that
40
+ you cause to be infringed by modifications or additions to the software. If you or your company make any
41
+ written claim that the software infringes or contributes to infringement of any patent, your patent license
42
+ for the software granted under these terms ends immediately. If your company makes such a claim, your patent
43
+ license ends immediately for work on behalf of your company.
44
+
45
+ ### Notices
46
+
47
+ You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these
48
+ terms. If you modify the software, you must include in any modified copies of the software a prominent notice
49
+ stating that you have modified the software.
50
+
51
+ ### No Other Rights
52
+
53
+ These terms do not imply any licenses other than those expressly granted in these terms.
54
+
55
+ ### Termination
56
+
57
+ If you use the software in violation of these terms, such use is not licensed, and your license will
58
+ automatically terminate. If the licensor provides you with a notice of your violation, and you cease all
59
+ violation of this license no later than 30 days after you receive that notice, your license will be reinstated
60
+ retroactively. However, if you violate these terms after such reinstatement, any additional violation of these
61
+ terms will cause your license to terminate automatically and permanently.
62
+
63
+ ### No Liability
64
+
65
+ As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will
66
+ not be liable to you for any damages arising out of these terms or the use or nature of the software, under
67
+ any kind of legal claim.
68
+
69
+ ### Definitions
70
+
71
+ The “licensor” is the entity offering these terms.
72
+
73
+ The “software” is the software the licensor makes available under these terms, including any portion of it.
74
+
75
+ “You” refers to the individual or entity agreeing to these terms.
76
+
77
+ “Your company” is any legal entity, sole proprietorship, or other kind of organization that you work for, plus
78
+ all organizations that have control over, are under the control of, or are under common control with that
79
+ organization. Control means ownership of substantially all the assets of an entity, or the power to direct its
80
+ management and policies by vote, contract, or otherwise. Control can be direct or indirect.
81
+
82
+ “Your license” is the license granted to you for the software under these terms.
83
+
84
+ “Use” means anything you do with the software requiring your license.
85
+
86
+ “Trademark” means trademarks, service marks, and similar rights.
package/README.md CHANGED
@@ -23,9 +23,9 @@ several over its life, one at a time, and it keeps all of them.
23
23
 
24
24
  [![Tests](https://github.com/alessio-ragni/k0-board/actions/workflows/ci.yml/badge.svg)](https://github.com/alessio-ragni/k0-board/actions/workflows/ci.yml)
25
25
  [![npm](https://img.shields.io/npm/v/k0-board)](https://www.npmjs.com/package/k0-board)
26
- [![License: MIT](https://img.shields.io/badge/License-MIT-informational)](LICENSE)
26
+ [![License: Sustainable Use](https://img.shields.io/badge/License-Sustainable%20Use-informational)](LICENSE)
27
27
 
28
- **Contents** · [Install](#install) · [How it is used](#how-it-is-used) ·
28
+ **Contents** · [Install](#install) · [k0 Cloud](#k0-cloud) · [How it is used](#how-it-is-used) ·
29
29
  [The backlog](#the-backlog) · [The ChangeLog](#the-changelog) · [What's New](#whats-new) ·
30
30
  [The files of a session](#the-files-of-a-session) · [What it costs](#what-it-costs) ·
31
31
  [Filling the board with what you have already done](#filling-the-board-with-what-you-have-already-done) ·
@@ -33,7 +33,7 @@ several over its life, one at a time, and it keeps all of them.
33
33
  [Shift+Enter starts a new line](#shiftenter-starts-a-new-line) ·
34
34
  [Pasting into the terminal](#pasting-into-the-terminal) ·
35
35
  [How it is put together](#how-it-is-put-together) · [Security](#security) ·
36
- [What is not here yet](#what-is-not-here-yet) · [Contributing](#contributing) · [Licence](#licence)
36
+ [What is not here yet](#what-is-not-here-yet) · [Contributing](#contributing) · [License](#license)
37
37
 
38
38
  ---
39
39
 
@@ -71,7 +71,9 @@ that and went out from a laptop.)
71
71
  | `k0-board start` | run the server in the foreground, installing nothing |
72
72
  | `k0-board restart` | restart the service |
73
73
  | `k0-board status` | is it running? exits 0 if it is, 1 if it is not |
74
- | `k0-board doctor` | what this machine can and cannot do, and why |
74
+ | `k0-board doctor` | what this machine can and cannot do, and why — and where k0 Cloud stands |
75
+ | `k0-board login` | sign in to [k0 Cloud](#k0-cloud) with GitHub or Google: opens the board, where the buttons are |
76
+ | `k0-board logout` | sign out; the board stays on this machine and stops syncing |
75
77
 
76
78
  `--yes` does not ask. `--from-source` points the service at the directory you are in instead of
77
79
  copying it, which is what you want while working on k0 itself. `--no-open` finishes without
@@ -149,13 +151,140 @@ That last one deserves a sentence of its own: a process with the Accessibility p
149
151
  send keystrokes to any application, and here it is granted to your `node`, not to a signed k0
150
152
  app. Skipping it breaks nothing — the prompt gets typed and the session starts by itself.
151
153
 
152
- k0 makes **exactly one network request**, and you can switch it off. Once a day it asks the public
153
- npm registry what the newest version of `k0-board` is, so the board can mention that there is one.
154
- The package name is in the address and nothing else is in the request: not the version you are
155
- running, not your repositories, not your commits, not your board, not an identifier of any kind.
156
- Nothing is downloaded and nothing is run — k0 cannot update itself. Set `"updateCheck": false` in `~/.k0/config.json` and and no
157
- socket is opened, ever. Everything else stays as it was: no fonts fetched, no telemetry, no
158
- `git fetch`.
154
+ k0 needs **an account**, and it talks to **exactly two places**. You sign in with GitHub or Google,
155
+ and your board is kept in sync with **k0 Cloud** — k0's own database, on Supabase, in the EU — so
156
+ it survives a lost laptop and can be read from a browser. The board you work on is still the copy
157
+ on this machine: without a connection k0 keeps working, and catches up when the connection is back.
158
+
159
+ The second place is the public npm registry. Once a day k0 asks it what the newest version of
160
+ `k0-board` is, so the board can mention that there is one. The package name is in the address and
161
+ nothing else is in the request: not the version you are running, not your repositories, not your
162
+ commits, not your board, not an identifier of any kind. Nothing is downloaded and nothing is run —
163
+ k0 cannot update itself. Set `"updateCheck": false` in `~/.k0/config.json` and that socket is never
164
+ opened. Everything else stays as it was: no fonts fetched, no telemetry, no analytics, no
165
+ `git fetch`, and the models still run here, through your own Claude Code.
166
+
167
+ ---
168
+
169
+ ## k0 Cloud
170
+
171
+ Your board lives on your machine and keeps working with no network at all. k0 Cloud holds a copy
172
+ of it, so it survives a lost laptop, reaches your other machines, and — coming with the site — can
173
+ be read from a browser at `k0-board.com/app/`.
174
+
175
+ Who owns which piece of it, where the keys live and how somebody is let in: [`docs/cloud.md`](docs/cloud.md).
176
+
177
+ ### Signing in
178
+
179
+ The first time you open the board it shows **Connect your account**, with a button for GitHub and
180
+ one for Google. Those are the only two ways in; there is no password of k0's own. The browser goes
181
+ to the provider, you say yes there, and it comes back to the board on this machine —
182
+ `http://k0.localhost:4319/auth/callback` — which finishes the sign-in by itself. k0 never sees a
183
+ password, and the one-time code that comes back is worth nothing on its own: it only works
184
+ together with a secret this machine made before sending the browser off (PKCE).
185
+
186
+ What keeps you signed in is written to `~/.k0/cloud.json`, readable by you and nobody else.
187
+
188
+ `k0-board login` from a terminal does the same thing: it opens the board, which is where the
189
+ buttons are, or says who is already signed in.
190
+
191
+ The screen only stands in front of the board when there is a way past it. If the cloud has no
192
+ sign-in switched on yet, the board simply opens: blocking it for something you cannot do anything
193
+ about would be k0's failure passed off as yours. Offline on the very first start, the screen says
194
+ the cloud cannot be reached instead of offering buttons that would not work.
195
+
196
+ ### Early access
197
+
198
+ Signing in is not the same as being let in. k0 is in early access: an account opens once it has
199
+ been approved, by hand. Until then the board says **You are on the list**, nothing is sent
200
+ anywhere, and the board goes on working exactly as before. It notices the approval by itself — no
201
+ restart, no second sign-in. *Use another account* on that screen signs out and starts again.
202
+
203
+ (Approving accounts is done from an admin page that is coming with the site.)
204
+
205
+ ### What goes up, and what never leaves the machine
206
+
207
+ Every few seconds, while you are signed in and let in, k0 sends what changed and fetches what your
208
+ other machines changed: epics, stories, tasks, decisions, rounds, checklists, dependencies, the
209
+ Log, and the sessions a story has had. A repository is named in the cloud by its `origin` remote,
210
+ cleaned of any password and of the difference between `git@` and `https://`, so the same
211
+ repository checked out on two machines is one column; a repository with no remote stays a name
212
+ known only to this machine.
213
+
214
+ What never leaves: which terminal window a session is in, the folder it is working in, and the
215
+ commit it started at. Nothing from your repositories either — not files, not diffs, not commits.
216
+
217
+ Sessions go up but do not come down. A session is a terminal on the machine that opened it; the
218
+ other machine has nothing to attach it to, so it would only be a ghost there. The cloud keeps
219
+ their status so the web board can show it.
220
+
221
+ When the same thing was changed in two places, a change made here and not yet sent wins over one
222
+ arriving from the cloud — it is what the person at this machine just did — and in the cloud a later
223
+ change wins over an older one that arrives late, so a laptop coming back after a day away does not
224
+ put yesterday's version over this morning's.
225
+
226
+ ### Offline, and keys with a `~`
227
+
228
+ A key is one number for your whole account: `K150` is the same story whichever repository it is in
229
+ and whichever machine is looking at it. So the number comes from the cloud, which is the only place
230
+ two machines can agree on what comes next. k0 asks for it the moment you create a story or an
231
+ epic, and waits at most two and a half seconds.
232
+
233
+ When the cloud does not answer, the story is made anyway, with a **provisional key**: `K~3`. It
234
+ works everywhere a key does. As soon as the cloud is back the sync gives it its real number, oldest
235
+ first, and renames its file in `.k0/`. Nothing is reserved in advance, so the numbers still run in
236
+ the order the stories were made.
237
+
238
+ ### Moving a board you already had
239
+
240
+ A board that existed before you signed in was numbered on this machine — per repository, if it is
241
+ older than k0 Cloud — and the cloud's counter starts somewhere else. Using the cloud's numbers
242
+ straight away would give your next story a `K1` the board already has. So the first time an
243
+ account is linked on a machine whose board has stories, **nothing is sent and no number is taken
244
+ from the cloud** until the board has been moved.
245
+
246
+ The board offers it: **Move your board to k0 Cloud**. *Show me the new numbers* lists every story
247
+ and epic, repository by repository, with its old key beside its new one, and says how many pieces
248
+ of text — a plan, a prompt, a decision — mention a key and will be updated with it. Nothing has
249
+ changed yet at that point. *Move it* then:
250
+
251
+ 1. copies the whole database to `~/.k0/backups/k0-before-cloud-<time>.db`, in one consistent file;
252
+ 2. renumbers every story and epic once, in the order they were made, starting from the cloud's
253
+ next number;
254
+ 3. rewrites the keys written inside the text — plans, prompts, bodies, decisions, rounds, the Log,
255
+ the checklist — within the same repository, since that is the only place a bare `K12` ever
256
+ meant anything;
257
+ 4. renames the files in `.k0/`;
258
+ 5. writes `~/.k0/backups/k0-before-cloud-<time>.keys.json`, every old key beside its new one;
259
+ 6. moves the cloud's counter past the board, and sends the whole board up.
260
+
261
+ When it is done the board says how many it moved, from which number, and where the two files are,
262
+ and stays on that page until you close it.
263
+
264
+ *Not now* means not now: the board keeps its old numbers and keeps working, and the offer comes
265
+ back the next time the board is opened.
266
+
267
+ ### The account chip
268
+
269
+ At the end of the top bar, once you are signed in: your picture, and a dot. **Green**, everything
270
+ is in the cloud. **Amber**, changes are waiting to go up — or a story still has a provisional key.
271
+ **Grey**, the cloud cannot be reached and the board is carrying on by itself. Click it for who is
272
+ signed in, **Sync now**, and **Sign out**.
273
+
274
+ ### Signing out
275
+
276
+ **Sign out** in that menu, or `k0-board logout`. The board stays on this machine exactly as it is;
277
+ it stops syncing, keys are counted on this machine again, and nothing is queued for later.
278
+
279
+ `k0-board doctor` has a *k0 Cloud* section: who is signed in, whether they have been let in,
280
+ whether the board still has to be moved, whether the cloud answers, and how many changes are
281
+ waiting.
282
+
283
+ ### Switching it off
284
+
285
+ `K0_CLOUD=off` in the server's environment switches the cloud off entirely: no sign-in screen, no
286
+ chip, no socket. It is meant for working on k0 itself and for the tests. Without an account, keys
287
+ are still one counter for the whole board rather than one per repository, kept on this machine.
159
288
 
160
289
  ---
161
290
 
@@ -357,8 +486,8 @@ that asked for it, close every session, restart k0 itself — the server stays u
357
486
  stays green. This is the whole reason it exists: a dev server started inside a session belongs to
358
487
  that session, and dies with it.
359
488
 
360
- **k0 never asks the server whether it is up.** Nothing here opens a socket — the one request k0
361
- makes goes to npm, and it is about versions, not about you. "Up" means the process is alive *and*
489
+ **k0 never asks the server whether it is up.** Nothing here opens a socket to it — k0 talks to its
490
+ own cloud and to npm, and to nothing it finds running on your machine. "Up" means the process is alive *and*
362
491
  the operating system says it is holding a TCP port
363
492
  open. That is stronger evidence than a reply would be, and it is where the port in the tooltip
364
493
  comes from — k0 never guesses a port, it reads the one your server actually chose.
@@ -599,12 +728,14 @@ the whole thing.
599
728
 
600
729
  ### The key, and where it sits
601
730
 
602
- Every epic, story and task gets a **key**: `K` plus a number, `K42`. It is counted per repository,
603
- shared between epics and stories, and it is **never reused and never reassigned** — not when the
604
- story moves under another epic, not when you delete it, not when the repository is renamed. Two
605
- repositories can both have a `K42`, and that is intended: a key means something inside its
606
- repository and nowhere else. Move a story to another repository and it is given a key from *that*
607
- repository, rather than carrying a number into a place that already has one.
731
+ Every epic, story and task gets a **key**: `K` plus a number, `K42`. It is **one number for your
732
+ whole account** — every repository, every machine — shared between epics and stories, and it is
733
+ **never reused and never reassigned**: not when the story moves under another epic, not when you
734
+ delete it, not when the repository is renamed, and not when the story moves to another repository,
735
+ since there is no other `K42` there for it to collide with. The number comes from k0 Cloud's
736
+ counter; a story made while the cloud cannot be reached gets a provisional key, `K~3`, until the
737
+ sync gives it its real one — see [Offline, and keys with a `~`](#offline-and-keys-with-a-). Without
738
+ an account the same single counter is kept on this machine.
608
739
 
609
740
  Beside it there is a **position**: `1.12.1`. The first epic, its twelfth story, that story's first
610
741
  task. The position is worked out fresh every time it is shown and never stored, so it cannot
@@ -874,10 +1005,10 @@ not believe the paragraph above it.
874
1005
 
875
1006
  ### Who writes it
876
1007
 
877
- k0 does not. **Nothing about your work leaves this machine**, and that is worth more than a better
878
- paragraph: a model of its own would mean a key to keep, an account to configure, and your commit
879
- messages going out over a wire. The one request k0 makes is to the npm registry, asking after its
880
- own version; it carries no commits, no repository names and no identifier.
1008
+ k0 does not. **No model of k0's own reads your work**, and that is worth more than a better
1009
+ paragraph: a model of its own would mean a key to keep, a second account to configure, and your
1010
+ commit messages going out over a wire to somebody's model. The facts are gathered on this machine
1011
+ and written up here; what k0 Cloud keeps is your board, not your commits or your diffs.
881
1012
 
882
1013
  It does not need one. If you are running k0 you already have Claude Code installed, signed in and
883
1014
  paid for — that is the whole point of the board — so the model is already here. k0 works out the
@@ -920,7 +1051,7 @@ they were written. While the prose is being written they are what there is to re
920
1051
  are what you check it against.
921
1052
 
922
1053
  It is the same machinery as the ChangeLog, and it has the same shape: nothing is stored, no model
923
- of k0's own, no key and no account — the Claude Code you already pay for does the writing, on this
1054
+ of k0's own and no key of its own — the Claude Code you already pay for does the writing, on this
924
1055
  machine. Nothing is downloaded either. k0 cannot update itself; the most it can do is say a newer
925
1056
  version exists, and leave `npx k0-board@latest` to you.
926
1057
 
@@ -1618,8 +1749,13 @@ server/
1618
1749
  worktree.js a session working copy of its own: open it from the branch you are on, merge
1619
1750
  it back, destroy it. Never a push, never a pull request, never a conflict
1620
1751
  resolved for you, and it never runs tests or a build in there
1621
- update.js the one request k0 makes — what npm says the newest version is — and the
1622
- version jump that puts the mark next to k0 in the top bar
1752
+ update.js one of the two places k0 reaches outside — what npm says the newest version
1753
+ is — and the version jump that puts the mark next to k0 in the top bar
1754
+ cloud.js the other place k0 reaches outside, and the only door to k0 Cloud: signing
1755
+ in, the next K number, rows up and rows down. Plain fetch, no client library
1756
+ sync.js moves rows between the board and the cloud every five seconds, and the
1757
+ one-time move of a board that predates the account. Carries rows; decides
1758
+ nothing about what they mean
1623
1759
  paths.js where the board, the logs, the settings and the cache live
1624
1760
  settings.js the few things you can change, and the file that is the list of them —
1625
1761
  ~/.k0/config.json, written out with everything in it and re-read when it changes
@@ -1667,6 +1803,8 @@ web/ the four pages (html, css, js served exactly as they are)
1667
1803
  whatsnew.html what changed in k0 between the version you had and this one — whatsnew.js,
1668
1804
  whatsnew.css. Reached from the mark next to k0, and never opened by itself
1669
1805
  base.css colours, fonts and scale: the house variables, shared by all of them
1806
+ account.js the account on the board: the chip at the end of the top bar, and the screen
1807
+ in front of the board until you are signed in, let in and moved
1670
1808
  awake.js the one place that repeats anything: a job that runs only while its tab is in
1671
1809
  front of you, and takes a fresh reading the moment you come back to it. A page
1672
1810
  nobody can see must not be asking the server anything — asking is also how the
@@ -1708,6 +1846,11 @@ web/ the four pages (html, css, js served exactly as they are)
1708
1846
  commit-push-deploy/
1709
1847
  the road out: the documents, the tests, the commit, the push, and the tag that
1710
1848
  publishes. Also for whoever works on k0, and also not in the package
1849
+ supabase/ k0 Cloud's own side: migrations/ is its database (accounts, workspaces, the
1850
+ rows of every board, the counter), config.toml its sign-in settings. The secrets
1851
+ are in ~/.config/k0-cloud/.env, never in the repository
1852
+ site/ k0-board.com: static pages, no build. app/ is the read-only web board and the
1853
+ page where accounts are approved — both coming with the site
1711
1854
  docs/
1712
1855
  database.md the shape of the database as it is now, table by table, column by column
1713
1856
  method.md why a decision has to be an object, what a round of questions is for, and
@@ -1717,6 +1860,35 @@ test/ npm test — Node's own runner, no framework. See docs/testing.
1717
1860
  harness.mjs check(label, got, want), and the sections the labels are grouped under
1718
1861
  ```
1719
1862
 
1863
+ ### How the board reaches the cloud
1864
+
1865
+ The board's rules live on the machine, in SQLite, and they stay there: states, decisions, rounds,
1866
+ dependencies. The cloud does not model the board table by table. It keeps **one document per
1867
+ row**, keyed by a `uid` the machine gave that row, so a change to k0's own tables needs no change
1868
+ in the cloud. What the cloud does own is what a single machine cannot: who you are, whether you
1869
+ have been let in, which workspace your rows belong to — a personal one today, built so a team is a
1870
+ second kind of workspace and nothing else moves — and the one counter that numbers your stories.
1871
+
1872
+ **Changes are noticed by triggers, not by the code that makes them.** Every synced table has
1873
+ triggers that write a line into an `outbox` table on insert, update and delete. About forty places
1874
+ in `db.js` write to those tables, and a list of "remember to tell the cloud" calls would be forty
1875
+ chances to forget one; a trigger cannot be forgotten. Two switches decide whether the triggers
1876
+ write anything: one that is off until an account is linked, so a board with no cloud does not grow
1877
+ a queue for ever, and one that is on while rows that came *from* the cloud are being written, so
1878
+ they are not sent straight back.
1879
+
1880
+ A round, every five seconds, does three things in order: gives provisional keys their real
1881
+ numbers, oldest first; sends the outbox up as documents, with references to other rows written as
1882
+ `<column>_uid` because an integer id means nothing in another database; and fetches what other
1883
+ machines wrote since the last round, in the order that puts an epic before its stories and a story
1884
+ before its decisions. A row whose owner has not arrived yet is left for a later round rather than
1885
+ written pointing at nothing. A failed round never throws at the board: it says so in the chip and
1886
+ tries again.
1887
+
1888
+ In the cloud every row is fenced off by the database's own row-level rules: only a member of the
1889
+ workspace, with an approved account, can read or write it. The address and the key in `cloud.js`
1890
+ are public on purpose — the key identifies the project and grants nothing by itself.
1891
+
1720
1892
  ### What it reads, and what it never does
1721
1893
 
1722
1894
  k0 reads your repositories. It writes into one in three places, and all three are named here
@@ -1762,8 +1934,8 @@ Windows.
1762
1934
 
1763
1935
  The ChangeLog and the What's New page run Claude Code a second way: `claude -p` on the skill that
1764
1936
  writes them, with the facts on standard input and no terminal at all. Those are the only times k0
1765
- starts a model, and they still open no socket of k0's own — the request is Claude Code's, made
1766
- with your own account, from your own machine. Both pages can be writing at once without either
1937
+ starts a model, and the model runs on Claude Code's own connection — the request is Claude Code's,
1938
+ made with your own Claude account, from your own machine, and it goes nowhere near k0 Cloud. Both pages can be writing at once without either
1767
1939
  cancelling the other. Those runs cannot come back as stories: `sessions.js` drops `claude -p` when it looks for
1768
1940
  sessions to import, which is also how it tells a hundred and forty real sessions from eight
1769
1941
  hundred automated ones.
@@ -1840,6 +2012,25 @@ Field notes the code takes for granted.
1840
2012
  XML, and with a `1b` byte inside, that XML is not even valid. And `killall cfprefsd` twice, not
1841
2013
  once: **before** writing, so the preferences daemon flushes what it still holds from the Terminal
1842
2014
  that just quit, and **after**, or nobody sees the change.
2015
+ - **The cloud's numbers cannot be used before the board has moved.** An old board was numbered on
2016
+ the machine, and the cloud's counter starts at 1: the first story numbered by the cloud would
2017
+ collide with a `K1` already on the board. So a linked machine with stories records nothing and
2018
+ asks for no number until the move has run — and the move pushes the cloud's counter past the
2019
+ whole board before the first sync.
2020
+ - **There is no way to look at the cloud's next number without using it.** A number asked for is a
2021
+ number handed out. So the move's preview takes one, and the move then starts from exactly that
2022
+ number; the gap it would otherwise leave never appears.
2023
+ - **`VACUUM INTO`, not a copy of `k0.db`.** With the write-ahead log on, the file alone is not the
2024
+ board — the last changes may still be in `-wal`. The copy taken before the move is one consistent
2025
+ file with all of it folded in.
2026
+ - **Keys inside text are rewritten in one pass, with the whole map.** One key after another would
2027
+ turn a `K3` that became `K12` into whatever `K12` became.
2028
+ - **Supabase's new `sb_secret_…` keys cannot be sent as a Bearer token.** The admin API — creating
2029
+ a throwaway account, approving one from a script — needs the `service_role` JWT instead. Both
2030
+ live in `~/.config/k0-cloud/.env`.
2031
+ - **`supabase config push` fails on the storage part with CLI 2.106**, but the auth part — the
2032
+ redirect addresses, the providers — has already been applied by then. Check the dashboard rather
2033
+ than trusting the exit code.
1843
2034
 
1844
2035
  ### Where the repository list comes from
1845
2036
 
@@ -1868,14 +2059,17 @@ deleting**: the stories stay in the database, and if the directory comes back so
1868
2059
 
1869
2060
  The server listens on loopback only, and refuses requests that arrive with a `Host` or `Origin`
1870
2061
  it does not recognise — which is what stops a web page you happen to have open from talking to it.
1871
- HTML files from your repositories are shown in a sandbox with no permissions. There is no account
1872
- and no token: anything already running as you on this machine can reach the API, and that is worth
2062
+ HTML files from your repositories are shown in a sandbox with no permissions. The local API has no
2063
+ login of its own: anything already running as you on this machine can reach it, and that is worth
1873
2064
  knowing rather than glossing over.
1874
2065
 
1875
- **One request leaves this machine, and it is about k0 rather than about you.** Once a day k0 asks
1876
- the public npm registry what the newest version of `k0-board` is, so the board can say there is
1877
- one. The package name is in the address and nothing else — nothing about you, your repositories,
1878
- your commits or your board — nothing is downloaded, and `"updateCheck": false` in `~/.k0/config.json` switches it off entirely.
2066
+ **k0 talks to two places, and to nothing else.** The first is k0 Cloud, where your board is synced
2067
+ once you have signed in with GitHub or Google. The token that keeps you signed in sits in `~/.k0/`,
2068
+ readable by you alone, and in the cloud every workspace's rows are fenced off from every other's by
2069
+ the database itself. The second is the public npm registry, once a day, asking what the newest
2070
+ version of `k0-board` is. The package name is in the address and nothing else — nothing about you,
2071
+ your repositories, your commits or your board — nothing is downloaded, and `"updateCheck": false`
2072
+ in `~/.k0/config.json` switches it off entirely. No telemetry, no analytics, no fonts from anywhere.
1879
2073
 
1880
2074
  The full picture, and how to report a problem privately, is in [SECURITY.md](SECURITY.md).
1881
2075
 
@@ -1898,6 +2092,14 @@ Yes please — especially if you are on Linux or Windows, where nobody has tried
1898
2092
  [CONTRIBUTING.md](CONTRIBUTING.md); the fastest useful thing you can send is the output of
1899
2093
  `k0-board doctor`.
1900
2094
 
1901
- ## Licence
2095
+ ## License
2096
+
2097
+ k0 is source-available under the [Sustainable Use License](LICENSE) © Alessio Ragni ·
2098
+ [alessioragni.com](https://alessioragni.com). Every line of it is public, and you may use it, change
2099
+ it, and run it for yourself or inside your company, for your own work; you may also pass it on,
2100
+ free of charge, for non-commercial purposes. What it does not allow is offering k0 to other people
2101
+ as a paid or hosted service of your own. It is not an open source license in the OSI sense, and k0
2102
+ does not call itself one.
1902
2103
 
1903
- [MIT](LICENSE) © Alessio Ragni · [alessioragni.com](https://alessioragni.com)
2104
+ Versions up to and including 0.5.0 were released under the MIT License, and they stay that way: a
2105
+ copy of one of those keeps every right MIT gave it.