@klok-integration/cli 0.7.327 → 0.9.345

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.
@@ -9,7 +9,8 @@ content arrives here. There are two kinds, and they are edited differently:
9
9
  from the `KlokProjectDocumentationV1` payload the source repository's `main` pipeline publishes, replaces
10
10
  everything under `docs/` on every run and commits the AI sections under `docs/_ai/`. It reads only tenant klok's
11
11
  payloads today (klok/integration/klok-documentation-egress#2). Never edit it: a change made here is overwritten by
12
- the next run. There are exactly two places to change it:
12
+ the next run. The one exception is `klok-documentation-settings.json` at the root (see *Rules*). There are exactly
13
+ two places to change its content:
13
14
  * `klok-docs/` in the source repository, in a merge request there: the hand written pages, their order and
14
15
  chapter titles (`toc-manifest.json`), and where an AI section appears (`<!-- KLOK:GENERATED:START <id> -->` …
15
16
  `<!-- KLOK:GENERATED:END <id> -->`);
@@ -28,7 +29,15 @@ content arrives here. There are two kinds, and they are edited differently:
28
29
  writes it. `"state": "retired"` there makes `klok docs publish` take every doc id it names (`docId`,
29
30
  `previousDocIds`) off the portal instead of uploading; `--dry-run` lists them. Do not edit it to keep a project
30
31
  published: its state follows the source project.
31
- * Visibility follows `meta.json` `scope` (`global`, `tenant`, `domain`, `system`); a page that must not be seen by
32
- another domain belongs in a project with that scope, not behind a note.
32
+ * Who reads the documentation is its visibility, set in `klok-documentation-settings.json` at the root
33
+ (`{"visibility": "global"}`): `public` (anyone, without login), `global` (every signed-in person of every tenant),
34
+ `tenant` (every member of the owning tenant), `members` (the owning domain's members and the tenant's owners, admins
35
+ and developers) or `admins` (the owners and admins of the owning domain and tenant). Without the file the default of
36
+ the documented path applies: `public` in a `public` group, `global` in tenant klok's `global` group, `tenant`
37
+ everywhere else. It is the one file people edit in a generated documentation project, the egress never touches it,
38
+ and tenant owners and admins change it, in GitLab or with `klok docs visibility --set`. Documentation is open by
39
+ default: narrow it only when someone asks for it. `klok docs publish` fails on a level that is not one, and its
40
+ dry run prints the level it would publish with. `scope` in `meta.json` decides nothing; a page that must not be seen
41
+ by the rest of the tenant belongs in a project with that visibility, not behind a note.
33
42
  * Preview locally with `znai preview --source=docs`, and check what a publish would do with
34
43
  `klok docs publish --dry-run`; the `llm.txt` the build generates is what agents read.
@@ -46,8 +46,11 @@ What the answers mean:
46
46
  * **404**: the project is not published yet. Its hand written pages are in the repository's `klok-docs/` on
47
47
  `main`, the source of the same site: `git -C <repo> fetch origin && git show origin/main:klok-docs/<page>.md`
48
48
  (`toc-manifest.json` lists the pages). Read them there; nothing else is a substitute.
49
- * **401 or 403** (no token, or your GitLab account is not a member of the tenant or domain): say so and ask for a
50
- token or for access. Never guess what the page says, and never try another way in.
49
+ * **Public documentation needs no token:** `klok docs read` and `klok docs list` work without one and say the read
50
+ was anonymous. Everything else needs your GitLab token.
51
+ * **401 or 403** (no token for documentation that is not public, or your GitLab account is not among the project's
52
+ readers, which its visibility decides): say so and ask for a token or for access. Never guess what the page says,
53
+ and never try another way in.
51
54
 
52
55
  The `klok-docs` skill describes the lookup in detail. Cite the doc id you relied on, and the `fetchedAt` from
53
56
  `klok docs read --json`, in your answer or merge request description.
@@ -80,7 +83,7 @@ it when a task touches the platform:
80
83
 
81
84
  | File | Holds |
82
85
  |---|---|
83
- | `knowledge/platform-rules.md` | the current platform rules: principles, naming, route ids and legs, topics, datamodel classes, write narrow and consume wide, claim check, tasks, the ODL |
86
+ | `knowledge/platform-rules.md` | the current platform rules: principles, roles and access (owners, admins, developers), naming, route ids and legs, changes and work (change requests, implementation issues, beads), topics, datamodel classes, write narrow and consume wide, claim check, tasks, the ODL, documentation and who reads it |
84
87
  | `knowledge/glossary.md` | the Klok terms and what they mean |
85
88
  | `knowledge/kloker-identity.md` | Kloker's identity and writing style |
86
89
  | `knowledge/roles/` | the role handbooks of the Kloker role models |
@@ -332,9 +335,9 @@ access, Keycloak broker clients or a service that serves several tenants.
332
335
  name and rejects a payload that claims another one.
333
336
  * **Write narrow, consume wide.** A tenant publishes only in its own namespace, `<tenant>[_<env>]/<domain>`; nobody
334
337
  holds `publish` in another tenant's namespace, not even on one topic. Reading elsewhere is a `consume` grant on a
335
- named topic, approved by the owner and recorded in Git in the owning tenant. The topic keeps its own name; the
336
- reader is known by its subscription (its route id, `DGR012E1_...`). When the content belongs to one reader, the
337
- publisher may choose that reader's tenant slug as the purpose
338
+ named topic, approved by an owner or admin of the topic's tenant or domain and recorded in Git in the owning
339
+ tenant. The topic keeps its own name; the reader is known by its subscription (its route id, `DGR012E1_...`). When
340
+ the content belongs to one reader, the publisher may choose that reader's tenant slug as the purpose
338
341
  (`persistent://konvoj/hr/PersonnelScheduleExportV1_degerfors`); that is the publisher's choice, not a condition
339
342
  for reading across tenants.
340
343
  * **Platform services** (logs, the ODL, tasks, AI, documentation) are klok services, and today each one is
@@ -347,15 +350,16 @@ access, Keycloak broker clients or a service that serves several tenants.
347
350
  is `service-account-<client id>`; one CI broker client per tenant; every broker client attaches the client scope
348
351
  `pulsar` (audience and the `nbf` claim Pulsar requires) instead of copying mappers.
349
352
  * **Grants:** `publish` and `consume` on the service's own domain and its tenant's `common`, as namespace grants;
350
- anything in another domain or tenant is `consume` on one topic, never `publish`, approved by its owner and
351
- recorded in Git in the owning tenant. Pulsar's `produce`/`consume` appear only inside a grant command.
353
+ anything in another domain or tenant is `consume` on one topic, never `publish`, approved by an owner or admin of
354
+ its tenant or domain and recorded in Git in the owning tenant. Pulsar's `produce`/`consume` appear only inside a
355
+ grant command.
352
356
  * **Who applies it:** Ansible (`klok/environment/klok-environment-setup`, `keycloak.yml` and `pulsar.yml`) applies
353
357
  what those files declare: today the platform and tenant klok's services, plus any entries a person adds there for
354
358
  another tenant's service (a playbook per tenant: klok/environment/klok-environment-setup#35). Broker access (a
355
359
  tenant, a namespace, a topic, a grant) changes only through a merge request to those Pulsar files. klok.dev merges
356
- what needs no approval (the generic topic of every datamodel) and what an owner approved in klok.dev, and applies
357
- topics and grants from the files; Ansible, run by a person, applies the same files and alone creates namespaces and
358
- revokes grants. klok.dev provisions no broker clients yet (klok/application/frontend-klok-dev#51). A topic or grant
360
+ what needs no approval (the generic topic of every datamodel) and what an owner or admin approved in klok.dev, and
361
+ applies topics and grants from the files; Ansible, run by a person, applies the same files and alone creates
362
+ namespaces and revokes grants. klok.dev provisions no broker clients yet (klok/application/frontend-klok-dev#51). A topic or grant
359
363
  made only in the broker's admin API is drift.
360
364
  * **Topics are provisioned, never created by the broker.** A topic exists when its tenant's Pulsar file lists it and
361
365
  the file is applied; its `_DLQ`, and the `_Response` of a `_Request` topic, come with it. `./gradlew klokTopics`
@@ -375,8 +379,11 @@ Klok documentation has three levels, and a change is finished only when all thre
375
379
  project outside them includes `klok/environment/build-ci-templates:/klok-docs-send.yml`).
376
380
  `klok docs send --dry-run` shows what would be sent. KlokDocumentationEgress
377
381
  (`klok/integration/klok-documentation-egress`, KLK007) builds the repository's documentation project from it. That
378
- documentation project is output, and nobody edits it. This runs for tenant klok only: another tenant has no
379
- documentation broker client, so its `klok_docs_publish` job fails and, being `allow_failure`, only warns
382
+ documentation project is output, and nobody edits it except `klok-documentation-settings.json` at its root, which
383
+ says who reads it (`public`, `global`, `tenant` by default, `members` or `admins`) and which tenant owners and
384
+ admins change, in Git or with `klok docs visibility --set`; documentation is open by default and narrowed only when
385
+ someone asks. This runs for tenant klok only: another tenant has no documentation broker client, so its
386
+ `klok_docs_publish` job fails and, being `allow_failure`, only warns
380
387
  (klok/environment/klok-environment-setup#33), and the egress reads only klok's topic
381
388
  (klok/integration/klok-documentation-egress#2). There are two places to change a project's documentation:
382
389
  `klok-docs/` in the source repository (including the `KLOK:GENERATED` markers that place AI sections in a page),
@@ -22,7 +22,7 @@ text of its own.
22
22
  | File | What it is | Composed into |
23
23
  |---|---|---|
24
24
  | `glossary.md` | the Klok terms and their meanings, with the rule never to guess a term | the role models `Kloker-Integration-Architect` and `Kloker-Integration-Developer` |
25
- | `platform-rules.md` | the current platform rules: principles, naming, route ids and legs, topics, datamodel classes, write narrow and consume wide, claim check, tasks, the ODL | the agent runner's doctrine, the role models |
25
+ | `platform-rules.md` | the current platform rules: principles, roles and access (owners, admins, developers), naming, route ids and legs, solutions, changes and work (change requests, implementation issues, beads), topics, datamodel classes, write narrow and consume wide, claim check, tasks, the ODL, documentation and who reads it | the agent runner's doctrine, the role models |
26
26
  | `kloker-identity.md` | who Kloker is, and the Unslop writing style | every request to the models `Kloker` and `Kloker-nothink` |
27
27
  | `roles/integration-architect.md`, `roles/integration-developer.md` | only what is specific to the role; the rules come from `platform-rules.md` | the role models `Kloker-Integration-Architect` and `Kloker-Integration-Developer` |
28
28
  | `retired-patterns.txt` | conventions the platform no longer has, one pattern per line with the reason | tests that fail when a prompt teaches a retired rule |
@@ -16,6 +16,9 @@ it as the source does.
16
16
  | DLQ | Dead letter topic `<topic>_DLQ`, where a message goes after its retries are exhausted; it is provisioned with its topic |
17
17
  | Tenant | An organisation on the platform, and its security boundary; every topic, ODL object and GitLab group belongs to one tenant |
18
18
  | Domain | A business area inside a tenant. `common` is shared by the tenant's domains, `public` is open to anyone |
19
+ | Role | What a person may do, given by Keycloak groups; a person may hold any number of roles, in any tenants and domains. There are nine: Klok Framework Owner, Admin and Developer on the platform (`/klok/owners`, `/klok/admins`, `/klok/developers`), Tenant Owner, Admin and Developer (`/tenants/<tenant>/owners`, `admins`, `developers`) and Domain Owner, Admin and Developer (`/tenants/<tenant>/domains/<domain>/owners`, `admins`, `developers`). In code they are `KlokOwner`, `TenantAdmin`, `DomainDeveloper` and so on |
20
+ | Owner | The named main contact of the platform, a tenant or a domain; every tenant and domain has one or more. An owner is always also an admin of the same scope, so an owner may do whatever an admin may |
21
+ | Visibility | Who reads a documentation project on docs.klok.dev, widest first: `public` (anyone, without login), `global` (every signed-in person of every tenant), `tenant` (every member of the owning tenant, the default), `members` (the owning domain's owners, admins and developers and the tenant's), `admins` (the owners and admins of the owning domain and of the tenant). Set in `klok-documentation-settings.json` of the documentation project; documentation is open by default and narrowed only when someone asks |
19
22
  | Route, route id | One Camel route per Java class (except a `KlokRestApi`, one per operation, and a `KlokRuntimeInstanceRoute`, one per instance `<RouteId>#<instanceKey>`). Its id is `<TENANTSHORT><NNN><LEG><seq>_<Description>`, for example `KLK007T1_PublishKlokStandard`; the class name is the id |
20
23
  | Leg | The letter in a route id: I ingress, P processing, E egress, A API, S sub route, T timer |
21
24
  | Ingress, egress | An ingress is a route that takes a message from outside the platform onto the broker; an egress takes a message off the broker to the outside. An ingress is an onramp or a channel adapter, an egress an offramp or a channel adapter. As a word for a service (`klok-postmark-ingress`) it says what the service is, never a permission |
@@ -24,6 +27,15 @@ it as the source does.
24
27
  | Tenant short name | `TENANTSHORT`, three upper case letters that start every solution and route id of a tenant: the first three consonants of the tenant's name (`KLK` for klok, `DGR` for degerfors), decided by the platform |
25
28
  | Solution | The business flow a set of routes implements; its id is the route id's prefix, for example `KLK007`. The id is allocated once, by a merge request in the tenant's `integration-solutions` registry, and never reused; a solution is reserved, active or retired |
26
29
  | Solution document | The `README.md` of a solution in the tenant's `integration-solutions` registry: its services, legs and flows, kept true to what is built |
30
+ | Change request | A change to the integration landscape: an issue in the tenant's `integration-solutions` registry labelled `change-request`, named `<registry path>#<iid>`; its questions, design, issues, beads and merge requests link back to it |
31
+ | Question | An issue in the registry labelled `question` and linked to a change request: something a person answers, in a comment, before the change can be planned |
32
+ | Design merge request | The one merge request in the registry that designs a change request: it brings the solution document to the new steady state and adds the issue manifest |
33
+ | Issue manifest | `ISSUE_MANIFEST.json` in `solutions/<KEY>_<slug>/changes/<iid>/` of the registry: the implementation issues a change request needs, each `planned`, or `approved` by a person; issues are made from it once it is on `main` |
34
+ | Implementation issue | An issue in the project that does the work, made from an approved manifest item; it carries `solution:<KEY>`, a footer that names its change request, and a link to it |
35
+ | `kloker`, `developer` | The labels of an implementation issue that say who builds it: Kloker, bead by bead, or a developer in a capable harness. Never both |
36
+ | Bead | A file in `.beads/` of a repository that describes one small change of an implementation issue, small enough for Kloker with no judgement left (the bead sizing rules); it is done when the merge request that implements it merges |
37
+ | Harness | The program a person runs a coding agent in, such as Claude Code, Codex, Copilot or OpenCode; only in this literal sense |
38
+ | Background Kloker | The agent service's loop that follows a tenant's `kloker/policy.json` in Git: it repairs Kloker's merge requests and picks up the open beads of `kloker` issues |
27
39
  | Correlation id | `klok-correlation-id`: follows one business flow across routes and messages |
28
40
  | Task | Long-running work tracked by the platform (`KlokTaskV1` events, visible in klok.dev and the task API), for example an `ai.chat` task that asks Kloker for text |
29
41
  | Datamodel | A versioned data contract; the major version is in the name (`CustomerV1`). Classes: public (A), common (B) and domain (C) are XSD in a Git project of their own with generated Java, Python and TypeScript; system (X) models one external system and may be plain Java classes. All four classes may travel on the broker |
@@ -32,11 +32,36 @@ documentation or the dependency catalog can give you.
32
32
  anyone.
33
33
  * AI proposes, a human approves, CI verifies. Every write goes through a merge request, an issue or a draft that a
34
34
  person accepts.
35
+ * Documentation is open by default. Every member of a tenant reads all of the tenant's documentation, and a
36
+ documentation project is narrowed to its domain or to the admins only when someone asks: what is built gets reused
37
+ only when people can find it and read it.
35
38
  * A deliberate deviation from these rules is tagged `[TACTICAL]` in the solution document, with its cost and the
36
39
  condition for removing it. Never deviate silently.
37
40
  * Forbidden even as tactics: reading or writing another service's database, a topic carrying several datamodels,
38
41
  and state in a route's memory that the next message depends on.
39
42
 
43
+ ## Roles and access
44
+
45
+ A person's roles are Keycloak groups, and a person may hold any number of them, in any tenants and domains.
46
+
47
+ | Role | Keycloak group | Appointed by |
48
+ |---|---|---|
49
+ | Klok Framework Owner | `/klok/owners` | by hand in Keycloak |
50
+ | Klok Framework Admin | `/klok/admins` | by hand in Keycloak |
51
+ | Klok Framework Developer | `/klok/developers` | by hand in Keycloak |
52
+ | Tenant Owner | `/tenants/<tenant>/owners` | a platform admin: `owners` in tenants.yml |
53
+ | Tenant Admin | `/tenants/<tenant>/admins` | a platform admin: `admins` in tenants.yml |
54
+ | Tenant Developer | `/tenants/<tenant>/developers` | the tenant's owners and admins, in klok.dev |
55
+ | Domain Owner | `/tenants/<tenant>/domains/<domain>/owners` | the tenant's owners and admins, in klok.dev |
56
+ | Domain Admin | `/tenants/<tenant>/domains/<domain>/admins` | the tenant's owners and admins, in klok.dev |
57
+ | Domain Developer | `/tenants/<tenant>/domains/<domain>/developers` | the tenant's owners and admins and the domain's, in klok.dev |
58
+
59
+ * Every tenant and domain has one or more owners, its named main contacts. An owner is always also an admin of the
60
+ same scope: whatever reads the groups treats an owners group as owners and admins, and the person is kept in both
61
+ groups.
62
+ * An approval in a tenant or a domain (a topic, a broker grant, access to documentation) is given by an owner or an
63
+ admin of that tenant or domain. Klok Framework Owners and Admins act on every tenant.
64
+
40
65
  ## Routes and naming
41
66
 
42
67
  * One Camel route per Java class. The route id is the class name, the configuration prefix and the solution key:
@@ -96,6 +121,52 @@ documentation or the dependency catalog can give you.
96
121
  * New development and maintenance are one process: a change to a leg brings the solution document to the new steady
97
122
  state in the same change set, and `klok solutions check` compares the documents with the code on `main`.
98
123
 
124
+ ## Changes and work
125
+
126
+ * A change to the integration landscape starts as a **change request**: an issue in `<tenant>/integration-solutions`
127
+ labelled `change-request`, `solution:<KEY>` (`solution:new` while the solution has no id) and `change:<kind>`, named
128
+ `<registry path>#<iid>` (`acme/integration-solutions#12`). Everything made for it links back to it. A question to a
129
+ person is an issue in the registry labelled `question` and linked to the change request; the answer is a comment, and
130
+ closing the question says it is answered. A comment a tool writes to say where a change stands carries
131
+ `<!-- klok:status -->`, and the planner reads past it.
132
+ * **The design is one merge request** in the registry that mentions the change request (`Refs <registry>#<iid>`). It
133
+ brings the solution document to the new steady state, where every leg the change adds is `planned` on every line
134
+ that names it, and adds the plan: `solutions/<KEY>_<slug>/changes/<iid>/ISSUE_MANIFEST.json` with one
135
+ `issues/<stableKey>.md` per implementation issue. Planning again while it is open adds to the same merge request. A
136
+ person approves an item by setting it `approved` in the manifest; issues are created only from a plan on `main`, so
137
+ merging the design is what lets them be made.
138
+ * **An implementation issue** lives in the project that does the work. It carries `solution:<KEY>`, a `relates_to` link
139
+ to the change request and to the issues it depends on, and a footer that names its change request, solution, stable
140
+ key, manifest path and dependencies. Every merge request Kloker opens carries `klok-integration-agent`; a draft whose
141
+ build never passed also `build-failed`.
142
+ * **Kloker or a developer builds an issue, never both.** Bead creation either splits the issue into beads, labels it
143
+ `kloker` and opens a merge request with the bead files, or labels it `developer` and says in a comment why it cannot
144
+ be split. A developer builds a `developer` issue in a capable harness (Claude Code, Codex, Copilot, OpenCode), and
145
+ Kloker takes no bead of it.
146
+ * **Claim before you start.** Whoever works on a bead reports it `in_progress` before the work starts and `open` again
147
+ when they let it go, and nobody starts a bead someone else holds. A bead with an open merge request is
148
+ `needs_review`.
149
+ * **A bead is done when its merge request merges.** The merge request that implements a bead sets the bead file to
150
+ `done` with a progress entry, so the merge is what makes it done. A bead file on `main` that is `done` or `cancelled`
151
+ wins over any report, and a bead whose `dependsOn` are not all done on `main` waits.
152
+ * **Two failures hand a bead to a developer.** When Kloker has failed on a bead twice since its file last changed, the
153
+ bead is reported `blocked`, its issue's label `kloker` is replaced by `developer`, and a comment says why and links
154
+ the draft merge requests. Changing the bead file gives Kloker two new attempts.
155
+ * **The close rule.** A change request is ready to close when every implementation issue linked to it is closed and the
156
+ solution document on `main` describes what is built: no leg it added is still `planned`. A person closes it.
157
+
158
+ **Bead sizing.** A bead is small enough for Kloker, a cheap model with no judgement left, or it is not a bead:
159
+
160
+ * it changes one thing in one repository;
161
+ * every decision is already named: the paths, the route id, the topics with their purpose, the datamodel and its
162
+ version, the configuration keys;
163
+ * its acceptance criteria can be checked from the build and the diff;
164
+ * it builds on its own;
165
+ * it needs no missing fact and no step only a person may take (Vault, Ansible, Keycloak, a merge);
166
+ * it is small, under a day's work for a person.
167
+
168
+ An issue that cannot be split like that is a developer's.
169
+
99
170
  ## Topics and CloudEvents
100
171
 
101
172
  * `persistent://<tenant>[_<env>]/<domain>/<Model>[_<purpose>]`. Production has no environment suffix
@@ -125,8 +196,9 @@ documentation or the dependency catalog can give you.
125
196
  * Companions come with every topic and are never requested or listed on their own: `<topic>_DLQ` for every topic, and
126
197
  for a `_Request` topic its `_Response` (with that topic's `_DLQ`).
127
198
  * klok.dev declares the generic topic `<Model>` of every datamodel, and the ODL's change event topics. Every other
128
- topic (a purpose, a request/reply pair) and every grant is requested in klok.dev and approved by the owner (a
129
- TenantAdmin of the tenant or a DomainAdmin of the namespace), or added to the Pulsar file in a merge request.
199
+ topic (a purpose, a request/reply pair) and every grant is requested in klok.dev and approved by an owner or admin of
200
+ the topic's tenant or domain (a Tenant Owner or Admin, or a Domain Owner or Admin of the namespace), or added to the
201
+ Pulsar file in a merge request.
130
202
  * `./gradlew klokTopics` lists the topics a project needs (`build/klok-topics/topics.json`, with a warning for every
131
203
  topic the scan cannot resolve) and `./gradlew klokTopicCheck` asks klok.dev whether each exists and is granted to
132
204
  the service; in CI it blocks the deploy. A service checks the same at startup and does not start without them.
@@ -174,8 +246,9 @@ whether a model may travel on a topic; it decides how widely the model is shared
174
246
  * The topic decides the tenant, never the message. A service takes the tenant from the topic's namespace and rejects
175
247
  a payload or property that claims another tenant.
176
248
  * A tenant publishes only in its own namespace, `<tenant>[_<env>]/<domain>`. Nobody holds `publish` in another
177
- tenant's namespace. Reading elsewhere is a `consume` grant on one named topic, approved by the owner and recorded in
178
- Git in the owning tenant. The topic keeps its own name; the reader is known by its subscription.
249
+ tenant's namespace. Reading elsewhere is a `consume` grant on one named topic, approved by an owner or admin of the
250
+ topic's tenant or domain and recorded in Git in the owning tenant. The topic keeps its own name; the reader is known
251
+ by its subscription.
179
252
  * Platform services (logs, the ODL, tasks, AI, documentation) are klok services, today configured for tenant klok
180
253
  only. One that serves several tenants follows the same rule: a tenant's requests live in the tenant's namespace
181
254
  (`persistent://<tenant>[_<env>]/common/<Model>`), the service is granted `consume` on exactly those topics, and
@@ -183,8 +256,8 @@ whether a model may travel on a topic; it decides how widely the model is shared
183
256
  (`persistent://klok[_<env>]/<domain>/<Model>_<tenant>`).
184
257
  * Broker access (a tenant, a namespace, a topic, a grant) changes only in Git, in the owning tenant's Pulsar file in
185
258
  `klok/environment/klok-environment-setup`. klok.dev applies topics and grants from the file (merging what needs no
186
- approval and what an owner approved); Ansible, run by a person, applies the same files and alone creates namespaces
187
- and revokes. A topic or grant made only in the broker's admin API is drift.
259
+ approval and what an owner or admin approved); Ansible, run by a person, applies the same files and alone creates
260
+ namespaces and revokes. A topic or grant made only in the broker's admin API is drift.
188
261
  * One Keycloak client per running deployment, never shared and never used by a person. Broker rights are called
189
262
  `publish` and `consume`; *ingress* and *egress* say what a service is and are never permissions.
190
263
 
@@ -214,6 +287,24 @@ and reads, searches and writes synchronously through `odl()` (`get`, `search`, `
214
287
  request topics are in the `common` domain; a change event goes to the domain of the object. Tenant-tunable behaviour of a service (prompts, sections, languages) is a Klok
215
288
  standard shipped with the service plus a tenant override stored in the ODL.
216
289
 
290
+ ## Documentation
291
+
292
+ * Every repository documents itself in `klok-docs/`. Its documentation project, `<tenant>/documentation/<same path>`,
293
+ is generated output, published on docs.klok.dev under its doc id; nobody edits it except its
294
+ `klok-documentation-settings.json`.
295
+ * Who reads a documentation project is its visibility, widest first: `public` (anyone, without login), `global`
296
+ (every signed-in person of every tenant), `tenant` (every member of the owning tenant), `members` (the owning
297
+ domain's owners, admins and developers, and the tenant's) and `admins` (the owners and admins of the owning domain
298
+ and of the tenant). Klok Framework Owners and Admins read everything; Klok Framework Developers read like a
299
+ developer of every tenant.
300
+ * The default comes from the path and is the same rule for every tenant, tenant klok included: `public` for a project
301
+ in a `public` group, `global` for one in tenant klok's `global` group, `tenant` for everything else. A level is set
302
+ in `klok-documentation-settings.json` at the root of the documentation project (`{"visibility": "global"}`), in
303
+ Git or with `klok docs visibility --set`: tenant owners and admins set any level, domain owners and admins their
304
+ domain's projects up to `global`.
305
+ * Public documentation is read without a token (`klok docs read`, `klok docs list`); everything else with a GitLab
306
+ token or a login.
307
+
217
308
  ## Versions and delivery
218
309
 
219
310
  * Framework libraries, the Gradle plugin and datamodels are released with timestamped versions from `main` and
@@ -46,6 +46,27 @@ topic-dlq # dead letters are <topic>_DLQ
46
46
  (?i)\ba topic created in advance # every topic is listed in its tenant's Pulsar file before it is used; "in advance" is the only way
47
47
  (?i)\b(enable|turn on|switch on) (automatic|auto-?)[ -]?topic[ -]creation # the Klok broker runs with allowAutoTopicCreation=false; request the topic in klok.dev
48
48
  #
49
+ # klok.dev's work package model is retired (2026-10-29): a change request's work is implementation issues and beads in
50
+ # GitLab, linked to the change request.
51
+ (?i)\bwork[- ]packages?\b # the work package model is retired; a change request's work is implementation issues and beads in GitLab
52
+ (?i)\bTodo 360\b # the work package model is retired; a change request's work is implementation issues and beads in GitLab
53
+ # The planner loads the platform rules instead of restating the 11-step process of the old strategy chapter
54
+ # (klok-integration-agent#47); issues are linked with relates_to, and an issue is split into beads, not planned again.
55
+ (?i)\b11-step\b # the development process is described once, in the Klok user guide; a prompt loads the platform rules instead of restating a process
56
+ (?i)\bGitLab Free has no issue links\b # implementation issues are linked to their change request and their dependencies with relates_to, which every GitLab edition has
57
+ (?i)\blocal GSD\b # an implementation issue is split into beads by bead creation; there is no local planning step before it
58
+ #
59
+ # Tenant klok's documentation is read like every tenant's (2026-10-30): its owning scope is tenant, domain or system,
60
+ # and who reads a documentation project is its visibility, set in klok-documentation-settings.json of the
61
+ # documentation project. A project of tenant klok is read by every tenant only when it is set global, or sits in
62
+ # klok's global group.
63
+ (?i)\b(every|all)\b[^.\n]{0,20}\bklok\b[^.\n]{0,20}\bdocumentation\b[^.\n]{0,20}\b(is|are) (always )?(global|read by every tenant|visible to every tenant) # tenant klok's documentation is read by its own members by default; global is a visibility its documentation project sets
64
+ (?i)\bklok('s)? documentation (projects? )?(is|are) (always )?(global|read by every tenant|visible to every tenant) # tenant klok's documentation is read by its own members by default; global is a visibility its documentation project sets
65
+ (?i)\bglobal \(tenant\s*==?\s*klok\) # the owning scope is tenant, domain or system for every tenant; global is a visibility level, not tenant klok's scope
66
+ (?i)\bglobal documentation under\b # a standalone documentation project of tenant klok is read by klok's members unless its settings file sets global
67
+ (?i)\bvisibility follows [`'"]?meta\.json # who reads documentation is set in klok-documentation-settings.json; the scope in meta.json decides nothing
68
+ (?i)\bonly the platform tenant may claim\b # every tenant may set every visibility level, global and public included
69
+ #
49
70
  # Framework classes that do not exist in the Quarkus extension 2.0 and later.
50
71
  KlokSoapApi # removed in 2.0; SOAP is a KlokCustomRoute with camel-cxf
51
72
  KlokTenantBridgeRoute # does not exist; a KlokProcessingRoute in the reading tenant maps a granted topic
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: klok-cli
3
- description: Which klok command does what on the Klok platform (klok-cli, `@klok/cli`), with the full reference of every command and option in reference.md. Use before running a klok command you have not run in this task, when a task needs the local workspace current (`klok sync pull`), a list of the documentation (`klok docs list`), an answer about the integration landscape (`klok agent ask`), or a check of the solution registry, the deployed fleet, the catalog, a CI job, a deploy manifest, a pin, a bead or a datamodel, or a file transfer flow's sealed secrets and its write to the ODL.
3
+ description: Which klok command does what on the Klok platform (klok-cli, `@klok/cli`), with the full reference of every command and option in reference.md. Use before running a klok command you have not run in this task, when a task needs the local workspace current (`klok sync pull`), a list of the documentation (`klok docs list`), who reads a documentation project (`klok docs visibility`), an answer about the integration landscape (`klok agent ask`), or a check of the solution registry, the deployed fleet, the catalog, a CI job, a deploy manifest, a pin, a bead or a datamodel, or a file transfer flow's sealed secrets and its write to the ODL.
4
4
  ---
5
5
 
6
6
  # The klok command line
@@ -21,6 +21,8 @@ CLI version, generated from the program itself; when it is missing (an installer
21
21
  | what is dirty, unpushed or behind in the workspace, or moved, archived or gone in GitLab | `klok sync status` (`--fetch` for a current "behind") |
22
22
  | the documentation projects you may read | `klok docs list` |
23
23
  | one project's documentation | `klok docs read <doc-id>`; `klok docs id <tenant/group/.../repo>` derives a doc id |
24
+ | who reads each documentation project of the tenant, and whether the level is set or the default | `klok docs visibility` (`<doc-id>...` for some) |
25
+ | a documentation project's visibility changed, when the person asked for it | `klok docs visibility <doc-id>... --set <level> --reason "<why>"`, or `--default`; klok.dev checks that the person may |
24
26
  | an answer about the integration landscape, with links | `klok agent ask "<question>"`; `--session <first task id>` for a follow-up |
25
27
  | the impact of a datamodel change | `klok agent impact <datamodel> --change minor\|major\|remove` |
26
28
  | the next free solution id of the tenant, with why, or a new solution's id reserved by a merge request | `klok solutions next`, `klok solutions new "<name>" --dry-run`, then without `--dry-run` |
@@ -30,12 +32,23 @@ CLI version, generated from the program itself; when it is missing (an installer
30
32
  | what a CI job is, whether a change is documentation only, where CI time goes | `klok ci env`, `klok ci docs-only`, `klok ci timings` |
31
33
  | a pipeline's image in its deploy manifest | `klok manifest update --dry-run` (CI runs it without) |
32
34
  | a release pinned in an infrastructure repository | `klok pin update ... --dry-run` |
35
+ | a change request with its questions, design merge requests and implementation issues, and who builds each | `klok change show <registry>#<iid>` (or the URL of an implementation issue) |
36
+ | a change request planned into its solution document and one issue manifest | `klok agent plan --change <registry>#<iid>` |
33
37
  | the beads of the current repository | `klok bead list`, `klok bead show <id>`, `klok bead report <id>` |
38
+ | a bead taken before you start, let go, or done in the merge request that implements it | `klok bead claim <id>`, `klok bead release <id>`, `klok bead done <id> --merge-request <url>` |
34
39
  | the repository, root element and namespace a datamodel's class and name give | `klok datamodel names` |
35
40
  | an XSD checked the way the datamodel pipeline checks it | `klok datamodel validate` |
36
41
  | this repository's `klok-docs/` checked before the merge request | `klok docs build`, `klok docs verify` |
37
42
  | a sealing key for a tenant's klok-file-transfer, a secret sealed for a file flow, or flows written to the ODL from Git | `klok file-transfer keygen`, `seal`, `apply --dry-run` (then without) |
38
43
 
44
+ ## Working on a change request
45
+
46
+ Who builds an implementation issue, when a bead is claimed and when it is done are in `knowledge/platform-rules.md`,
47
+ *Changes and work*, next to `KLOK-AGENTS.md`. Follow it when a task names a change request, an implementation issue
48
+ or a bead: `klok change show` reads where the change stands, `klok bead claim` takes a bead before you start (a bead
49
+ someone else holds is refused), and `klok bead done --merge-request` sets it done in the merge request that implements
50
+ it. Never take a bead of an issue labelled `developer` unless you are that developer.
51
+
39
52
  ## The workspace
40
53
 
41
54
  `klok sync pull` brings the workspace current before you read it: every repository under the workspace root (config
@@ -72,7 +85,7 @@ patch` command: a person writes Vault, an agent hands the command over. The oper
72
85
  ## klok.dev
73
86
 
74
87
  The CLI is meant to do everything klok.dev does, as the person, but only part of the portal has its command yet
75
- (`klok whoami`, the agent commands, `klok solutions`). When a task needs something klok.dev shows and no klok command
88
+ (`klok whoami`, the agent commands, `klok solutions`, `klok docs visibility`). When a task needs something klok.dev shows and no klok command
76
89
  prints it, such as a broker topic's publishers and subscriptions, an ODL record or a task's events, say so and ask the
77
90
  person to look it up in klok.dev or to send it. Do not scrape the portal, and do not reach for credentials the task
78
91
  was not given (a service token, a secret read out of Vault) to get around the gap. `klok fleet status --broker` is an