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 +66 -1
- package/LICENSE +83 -18
- package/README.md +238 -36
- package/bin/k0-board.js +48 -1
- package/package.json +2 -2
- package/server/cloud.js +355 -0
- package/server/db.js +375 -58
- package/server/index.js +92 -2
- package/server/mirror.js +21 -0
- package/server/sync.js +383 -0
- package/server/update.js +3 -2
- package/web/account.js +265 -0
- package/web/base.css +93 -0
- package/web/index.html +1 -0
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.
|
|
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
|
-
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
[](https://github.com/alessio-ragni/k0-board/actions/workflows/ci.yml)
|
|
25
25
|
[](https://www.npmjs.com/package/k0-board)
|
|
26
|
-
[](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) · [
|
|
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
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
`
|
|
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 —
|
|
361
|
-
|
|
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
|
|
603
|
-
shared between epics and stories, and it is
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
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. **
|
|
878
|
-
paragraph: a model of its own would mean a key to keep,
|
|
879
|
-
messages going out over a wire
|
|
880
|
-
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
1872
|
-
|
|
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
|
-
**
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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.
|