Repository navigation
go-strictcli@v0.39.0
·
20 commits
to main
since this release
Adds NewGrant, ErrTimedOut, declared scratch directories (WithScratchDir and ctx.ScratchDir), WithArgsAfterSeparator, HTTP bodies streamed from a file, declared reads, redaction, and the Stdin, Timeout, and Mode effect options; App.Test changes nothing process-wide; test coverage is declared by the source-tree root; the check context factory receives the dispatch's Context; the effects-bypass check skips _test.go files; go-toml-edit is required at its new path.
Breaking
- [go-strictcli]
Test()changes nothing process-wide, so calls may overlap. Eachapp.Test(argv)call captures its output in its own streams, including the stdout and stderr of children run throughSpawnor a streamedRun, and the state a dispatch writes belongs to that dispatch instead of theApp: a test can run a long-lived command in one goroutine while it tests another, on one app or several.EffectLog()returns the most recently finished dispatch's log. Breaking: a byte a handler writes toos.Stdoutdirectly (fmt.Println) is no longer captured inResult.Stdout, and under--jsonTest()no longer arms the stray-stdout guard, which stays onRun(); write throughctx.Out, as--lint-framework-usealready requires. - [go-strictcli] Test coverage is declared by the source-tree root.
WithSourceTreeRoot(path)replacesWithTestCoverageDir(path): the app names the root of its source tree, and strictcli keeps the coverage state in.strictmetadata/.cli-test-coverage/under it, with per-process shard files inshards/(never committed) and the committed manifest inmanifest.json(formerlycoverage/andtest-coverage.json). Coverage is on only when that directory exists at construction.WithTestCoverageDiris now refused at registration, namingWithSourceTreeRoot. To migrate, move.strictcli/test-coverage.jsonto.strictmetadata/.cli-test-coverage/manifest.json(selfdoc layout migratedoes this) and declare the root instead of the directory. - [go-strictcli] The check context factory receives the dispatch's
*Context.SetCheckContextnow takesfunc(*Context) (CheckContext, error):checkandfailing-checkscall it with their own dispatch's context, so a tool can build its check context over that command's effects handle, and an error from the factory refuses the run with its message. A no-argument factory must be rewritten to take the*Contextand return(context, nil).
Features
- [go-strictcli] Stdin and Timeout effect options.
strictcli.Stdin(data)onRunandSpawnwrites bytes to the child's stdin and closes it, so secrets never enter argv; the would-do log and effect record show only the byte count (stdin: N bytes, content withheld).strictcli.Timeout(d)onRunandSpawned.Waitkills the child oncedhas passed and returns an error naming the command and the timeout; a non-positivedis refused, and dry mode renders(timeout: 30s). - [go-strictcli] Declared reads, a settable HTTP client, and redaction.
strictcli.Read()onHTTPandstrictcli.Observe()onRundeclare that one call changes nothing: it is legal in a read-only command, never recorded, and performed for real under--dry-run(a stale brand once a mutation has been recorded); withoutRead()every request stays a recorded mutation whatever its method.strictcli.WithHTTPClient(client)sets the client every live HTTP effect uses, so tests can point commands at anhttptestserver; without it the framework uses its own client with a 60-second timeout instead ofhttp.DefaultClient, andstrictcli.Timeout(d)now also bounds one HTTP request.strictcli.Redact(values...)replaces each value with«redacted»in the would-do log, the effect record, and every error the call returns, so an API key in a query string never reaches--dry-runoutput; an HTTP body renders only as its byte count.strictcli.Mode(mode)onWritesets the file's permission bits, rendered as(mode: 0600). - [go-strictcli] HTTP bodies streamed from a file.
strictcli.BodyFile(path)onHTTPsends a regular file as the request body, read while the request is sent instead of into memory first, with the file size as theContent-Length;strictcli.BodyFileRange(path, offset, length)sends one byte range of it, as a multipart upload's parts need. A missing or irregular file, a range outside the file, a repeated option, or a combination withBodyis refused at the call. Dry mode renders(body: N bytes from <path>), addingat offset Nfor a range, and the record carriesbody_file,body_offset, andbody_bytes. - [go-strictcli] A command can receive the arguments after
--unparsed.WithArgsAfterSeparator(name, help)hands every token after the first bare--to the handler throughctx.ArgsAfterSeparator(), untouched (a--dry-runor a second--there included), while the tokens before it parse as before, so a stray word is still refused. Help lists it underArguments:as-- <name>..., the help document publishes it asargs_after_separator(its command defaultnulljoins thedefaultsblock), andCalland the MCP tools take it as a list of strings under its name. A command without the declaration is unchanged. - [go-strictcli]
ErrTimedOut. An effects-handle run, spawned child's wait, or HTTP request that exceeds itsTimeoutreturns an error matchingstrictcli.ErrTimedOutwitherrors.Is(a redacted message too), so a caller tells a timeout from any other failure without reading the message. - [go-strictcli]
NewGrant.strictcli.NewGrant(name, reason, effectClass)builds a grant authorizing one effect class (ProcMutate,FileWrite, ...), so a caller declares a grant without spelling the struct's effect-class field. - [go-strictcli] Scratch directories. A command declaring
WithScratchDir()can askctx.ScratchDir()for a private directory under~/.cache/strictcli/scratch/, made on the first request and removed when the dispatch ends; making and removing it is never an effect, so a read_only command or a--dry-runcan run a program that writes for itself (a package manager's cache) there. A command that does not declare one is refused. Thecheckandfailing-checkscommands declare one, so a check context factory can hand it to its checks.
Fixes
- [go-strictcli] The README now says where an app's check list belongs: in the app's own package, passed with
WithChecks(path)or embedded withgo:embedand passed toWithChecksEmbed; strictcli has no standard folder or default path for it. - [go-strictcli] go-toml-edit is required at its new path,
github.com/stricttools/go-toml-edit, at 0.5.0. A program using strictcli no longer pulls the module under its old path. - [go-strictcli] The
effects-bypasscheck skips_test.gofiles. A test file builds only into the test binary, never into the program whose command handlers the check guards, so a test's handler or helper writing a fixture directly is no longer reported as a bypass.