feat(project): --gate reaches the build, and the bundle says which one

`project.create` called `build()` with five keyword arguments and no `gate=`,
so `okf project` screened by the package default and nothing anywhere said
that was a choice rather than the only option. The gate is not a segmentation
rule -- it is a screen about whether a document may be persisted at all -- so
it is the one flag this command owns that may move a bundle's bytes, and the
module docstring, the README paragraph and the test file's own claim are
corrected rather than left standing beside the new flag.

The default is `okf build`'s default, so an unflagged `okf project` is the
bytes it always was; the byte-equality invariant against `okf build` holds
unchanged. An unknown gate name still raises `gate_invalid` rather than
falling back -- a fallback reproduces the defect with an extra step.

Tests first, all three red: the gate name read back out of the bundle's own
`log.md` (not out of the call), the flag parsed by this command's parser, and
the unknown name refused.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-20 23:08:50 +02:00
commit 1c97e57212
3 changed files with 66 additions and 11 deletions

View file

@ -1409,7 +1409,7 @@ No security functionality is reimplemented here.
`--gate` takes `guard-trusted-source` (the default), `guard-user-upload` or
`none`, and the name is written into the bundle's `log.md` either way, so a
consumer holding a bundle can tell a screened one from an unscreened one
without asking. `okf project` has no such flag and takes the default.
without asking. `okf project` takes the same `--gate` with the same default: it is the one flag there that may move a bundle's bytes, and it is there because a command that cannot reach the gate screens by a default nothing said was a choice.
That paragraph is new, and the sentence above it was true of our own command
until 2026-09-15: `okf build` injected a permissive stub and no argument