You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(empty-values): sharpen why the server cannot just copy the rule
The section claiming a CLI rule cannot reach API callers had the mechanism wrong.
It implied its examples were empty values arriving at the server. They are not:
in 162 of the 166 cases an empty value and an absent flag produce an identical
payload, so nothing empty ever reaches the server and there is nothing there for
it to reject. That is why the server's half is a different rule rather than a
mirror of the CLI's.
The three examples are now a table, one per kind, with whose problem each payload
is in its own column - the CLI's, the server's, or neither. Two of them were
being read as the four combinations where an empty value differs from omitting
the flag; they are not, they are drawn from the 162 where it does not, which is
the whole point of citing them.
Dropped "a record the server cannot read back is not one it should accept". The
included-environments 500 is a plain defect that will be fixed regardless, and
stating it as a rule here prescribed one of two possible fixes - refusing the
write, or tolerating the read - which is not this document's call.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/handover/2026-08-13-empty-value-decision.md
+19-25Lines changed: 19 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -137,31 +137,25 @@ Not every request arrives through the CLI. A customer calling the API directly
137
137
keeps all of this, and the warnings in steps 1 and 2 will never see them, so the
138
138
measurement they produce covers CLI traffic only.
139
139
140
-
The findings split by where the behaviour actually lives. Reading the payloads
141
-
the CLI sends with `--debug` says which is which.
142
-
143
-
Some are the CLI's own doing, and a CLI rule genuinely settles them:
144
-
145
-
-`kosli attest generic --fingerprint ""` sends no fingerprint, to the
146
-
trail-scoped endpoint `/attestations/{org}/{flow}/trail/{trail}/generic`. The
147
-
CLI picked that endpoint. Someone calling the API chooses the artifact endpoint
148
-
or the trail endpoint deliberately, and is not misled.
149
-
-`--template-file ""` reading as "no template given" is the CLI's file handling.
150
-
151
-
Others are the server accepting something it should not, and a direct caller
152
-
reaches them just as easily:
153
-
154
-
-`--included-environments ""` sends a logical environment with **no**
155
-
`included_environments` field at all. The server returns 201 and then cannot
156
-
read the record back. Any client can send that payload.
157
-
-`create environment` sends `"description": ""` when no `--description` was
158
-
passed, and the server writes it over whatever was there. The CLI should not
159
-
send it, and the server should not treat an empty string as "erase this".
160
-
161
-
So the two halves want different fixes, and the server half is the one that
162
-
covers every client. That makes the server work in step 2 more than a
163
-
precondition for the CLI change: it is the part that closes the hole for
164
-
everyone.
140
+
The server cannot close that gap by copying the rule, because it mostly never
141
+
sees an empty value. When an empty value produces the same request as omitting
142
+
the flag - which is 162 of the 166 - the server receives an identical payload
143
+
either way, and there is nothing empty in it to reject.
144
+
145
+
Those 162 fall into three kinds, by whose problem the payload turns out to be.
146
+
One of each, read with `--debug`:
147
+
148
+
| Command | What reaches the server | Whose problem |
149
+
|---|---|---|
150
+
|`kosli attest generic --fingerprint ""`| no fingerprint at all, sent to the trail-scoped endpoint `/attestations/{org}/{flow}/trail/{trail}/generic`| the CLI's. It picked that endpoint. Someone calling the API chooses the artifact endpoint or the trail endpoint deliberately, and is not misled. The rule settles this one |
151
+
|`kosli create environment --included-environments ""`| a logical environment with **no**`included_environments` field, which the server accepts with a 201 and then cannot read back. Omitting the flag sends the same thing | neither's, for this decision. It is a plain defect, being fixed on its own account |
152
+
|`kosli create environment`|`"description": ""`, whether or not `--description` was passed | the server's. By the time it arrives this is not about empty values at all: it is a request meaning "nothing was specified", treated as an instruction to erase. A direct caller sends the same thing and gets the same result |
153
+
154
+
So the server's half of this is one rule, and not a mirror of ours: **an absent
155
+
or empty field is not an instruction to erase what is stored.** That covers every
156
+
client, including the ones the warnings cannot see, which makes the server work in
157
+
step 2 more than a precondition for the CLI change - it is the part that closes
0 commit comments