Versioned archive. You are viewing v0.38.0. For the latest released guidance, use Latest release. Report archive issues on GitHub.
evidencectl is Evidence Gateway adopter tooling. It creates key material and editable projects, compiles
production candidates, and invokes the evidence binary for Evidence Gateway semantic decisions. It does
not approve, deploy, promote, register production clients, or write production secret values.
Its client registration commands manage local development only.
Contract status
Section titled “Contract status”Evidencectl is outside the frozen Evidence Gateway Version 1 runtime contract. Its command line can
change before a compatibility promise covers it. Evidencectl compiles editable authoring input into
a closed bundle. The evidence runtime remains the authority for bundle validation and semantic
acceptance, fixture evaluation, secret validation, and startup acceptance.
The canonical adopter commands do not change the numeric Evidence Gateway Version 1
runtime.yaml grammar or the existing evidence-project.yaml marker.
Project workflow
Section titled “Project workflow”| Command | Inputs | Result | Does not do |
|---|---|---|---|
evidencectl check <project> | Editable project | Reports authoring completeness and field-addressed findings | Claim deployment closure, run fixtures, resolve secrets, or contact a dependency |
evidencectl check <project> --target <target> | Editable project and one explicit target | Adds the target’s governance, runtime structure, public keys, source connections, and governed-bundle validation | Require target-host paths or secrets to exist, run fixtures, or contact a dependency |
evidencectl check <project> --target <target> --production | Editable project and one explicit production or evidence-grade target | Refuses incomplete deployment closure under that target’s own assurance profile | Select a target, upgrade its profile, or prove live readiness |
evidencectl explain <project> [--target <target>] | Editable project and optional explicit target | Applies the same offline authoring validation, then reports status, findings, revision, and the authored inventory; includes target governance only when selected | Contact sources or expose secret and subject values |
evidencectl package <project> --target <target> --output <new-package> | Editable project and one explicit production target | Creates one closed package with SHA256SUMS; runtime remains in the target | Overwrite output, contact source services or OIDC, create production secrets, or start a listener |
evidencectl test <editable-project> [--target <deployment-target>] | An editable project with questions/, sources/, and referenced synthetic fixtures; an optional target supplies complete deployment governance | Privately compiles the project, then uses runtime bundle-check and bundle-evaluate | Start HTTP, call a source, or write a production audit entry |
evidencectl test <editable-project> --target <deployment-target> --explain | The same, and asks each evaluation to explain itself | Relays each fixture’s stage trace beside its step, or as that fixture’s trace field under --format json | Print a response, fact, derived, or selector value, or explain a served request |
evidencectl doctor --runtime-config <absolute-file> | Runtime file on its target host | Runs the runtime-owned startup dependency preflight without opening the public listener | Send an Evidence request or establish that a fixture passed |
evidencectl artifact inspect <target> | Deployment target whose runtime names the installed package | Inspects artifact custody without contacting dependencies | Establish live dependency readiness |
doctor --runtime-config opens the configured audit destination as startup does, so it refuses
while another Evidence instance holds that destination’s single-writer lock. To check a candidate
staged beside the instance it will replace, add --without-audit-lock: the audit hash key is
checked as startup checks it, and the audit directory and files are checked for ownership, mode,
write access, and a complete final entry. The lock stays with the running writer, so a second
writer is not detected. The JSON proofBoundary states this. Every other dependency is checked in
the same way. The refusal for a held lock names this option.
package is create-only. It rejects an existing output directory, unauthenticated or non-HTTPS
production HTTP sources, source transports with no stated production conditions, missing governance
metadata or fixtures, unresolved review markers, unknown fields, symlink traversal, and references
outside the allowed project directories. A failed package publishes no candidate.
check, test, package, source diff, and source update, plus the compatibility spelling
fixtures run, refuse a derivation whose answer reads a fact its question’s source
does not declare, with evidence.authoring.derivation-fact-undeclared against the derivation
file. A source declares an inline operation’s source.facts[].name, or the properties of a
referenced source’s closed factSchema. A registry field rename that a derivation still reads
under its old name therefore fails before source update installs anything. The check reads the
project, not the running registry: a candidate already deployed against a registry whose field is
then renamed still fails every request that reads it while /ready reports ready. Only literal
reads on the first answer parameter, such as facts["status"] and facts.status, are checked.
The operands of one ?? fallback are read together, so facts.new ?? facts.old passes while
either name is declared. A computed key such as facts[key] is not a literal read and is how a
derivation reads a fact the check should not see. It, a read inside a helper function, an
answer that rebinds or writes its first parameter, and an open fact schema are left to the
fixtures.
An ordinary check can succeed with status: incomplete and visible findings. Add
--deny-findings when any finding must refuse the command. All findings carry severity, code,
artifact, path, message, and suggestedAction. Human output is the default. Add the global
--format json option for the same result as structured JSON. A command that provides no JSON
report accepts only --format human, and the CLI reference shows which commands those are;
--format json on one of them is the usage error evidencectl.format.unsupported.
Under --format json, a command writes exactly one JSON object on standard output and nothing on
standard error. The object opens with ok, command, and status, in that order, then carries the
command’s own members. Every member name is camelCase; a map keyed by authored identifiers, such
as selectorProfiles, keeps those identifiers as its keys. command is the command path, such as check or
dev start, and status names what happened, such as complete, incomplete, passed, or
ready. ok is true exactly when the process exits 0. A refusal uses the same object with
ok: false, a diagnostics array whose entries each name the next step in suggestedAction, and
one of the statuses refused, failed, domain-refusal, usage-error, or
operational-failure. A command-line error that stops before a command is selected reports
command: "usage". Pending changes, such as a source add preview, are a status, never an exit
code.
The workflow exit classes are 0 for success, 1 for a domain refusal, denied finding, or failing
fixture, 2 for command-line usage, and 3 for an operational failure, such as a file, process,
or local session the command depends on being unavailable. These classes belong to adopter tooling;
they do not change the Evidence Gateway runtime verifier’s frozen exit contract.
evidencectl test and evidencectl fixtures run also accept --format junit. The run is the same;
standard output carries one JUnit XML document with a check suite for the bundle check and one
suite per fixture file, holding one test case per case the runtime’s trace named, and the human
summary moves to standard error. A run that evaluated no case carries a failing run suite, so the
document never reads greener than the exit code. Every other command refuses --format junit as a
usage error.
Compatibility spellings
Section titled “Compatibility spellings”The released new and fixtures run spellings remain available during the command
transition. The retired build spelling refuses the request and names package as its replacement.
New projects, examples, and current procedures use init, test, and package.
The doctor --project <target> compatibility form retains artifact inspection;
use artifact inspect <target> for that operation and reserve doctor --runtime-config for
live startup dependency checks. Every command that reads one project names it as a positional
<project> argument, defaulting to the current directory where the command allows it. The former
--project <project> spelling remains accepted, but hidden, on commands whose project is now
positional. Only source import, source diff, and source update, whose positional argument is
the export, and target new, whose positional argument is the target, document --project.
doctor keeps its visible --project <target> option, and the access commands and
audit show act on the current directory; none of these takes a positional project. Do
not combine a canonical positional project with its former --project flag; conflicting old and
new forms are usage errors.
Request preparation uses --response-format signed-jws|sd-jwt-vc so the
response choice cannot collide with global report formatting. The released
request prepare --format spelling remains accepted only for those two legacy
response values. Supplying both response selectors is a usage error.
Production input reference
Section titled “Production input reference”An editable project becomes a production build input only after it has:
- A
fixtures/regular file referenced by every production question. - Stable concept identifiers and production
governancemetadata in every question. <target>/governance.yamlwith bundle-owned fields for one environment.<target>/runtime.yamlwith one environment’s runtime bindings.- Public JWK files beneath
<target>/for every active and published service key referenced there.
governance.yaml is strict. It must carry version 1, an assuranceProfile of production or
evidence-grade, service, issuer, authentication, audit, subject binding, rate limits, signing,
optional response formats, and authority profiles. It cannot supply selector profiles, sources, or
requirements. It accepts logical secret:file/<name> references, not values or absolute secret
paths.
The output runtime document is copied byte-for-byte. Its paths and secret posture are accepted only
by the final target-host evidence check.
The maintained reference layout keeps the editable project under shared/evidence-project/ and each
complete deployment target under environments/<target>/evidence/. That layout is a repository
convention, not part of the --target path grammar. Do not use overlays, environment branches,
symlinks, or runtime substitutions. Git contains public keys and nonsecret provider configuration,
but no private JWKs, HMAC keys, provider tokens, auto-auth credentials, access tokens, live
responses, or real identifiers.
Local-only commands
Section titled “Local-only commands”evidencectl init requires a destination and exactly one authoring source:
evidencectl init <directory> --openapi <path-or-https-url> --profile localevidencectl init <directory> --transport sqlite-extract --profile localOpenAPI mode creates an authoring workspace whose source, question, and fixture directories remain
empty. SQLite mode creates a synthetic source, question, query, adapters, schemas, derivation, and
fixture. Both create disposable, unbound Evidence Gateway key material in the ignored owner-only
secrets/ directory. Neither creates a production target, issuer configuration, or deployable bundle.
evidencectl dev start [<project>] starts Evidence Gateway and the pinned local issuer on loopback.
When borrowing a shared issuer, pass --issuer-project <owner> and an exact --resource <URI>
registered for this Evidence Gateway service. The default resource is
urn:registrystack:evidence:local:gateway; a retained session keeps its selected resource and
refuses a different one on restart. The compiled governed bundle binds this audience.
The local issuer container’s name starts with thunderid-<prefix>-, with the prefix
evidence-dev by default. Pass --name-prefix <prefix> to dev start so parallel jobs on one
host can tell their containers apart: 1 to 32 lowercase letters, digits, and inner hyphens,
starting with a letter, such as ci-4711. The session records its prefix as namePrefix and keeps
it until dev clean: a restart without the flag reuses it, and a restart that names a different
prefix is refused.
For a nondefault resource, the compiler also derives distinct governed provider, issuer, and
service identifiers from that resource, so multiple local Evidence services remain separate in
Discovery.
It creates a session-scoped P-256 pair for an SD-JWT VC holder and an implicit caller pair only when the project has no explicit access
policy; explicit local clients use their keys under .evidence/clients/. Nothing under
.evidence/dev or .evidence/clients enters a production target.
evidencectl dev token <client> [<project>] obtains a fresh service token and writes an owner-only
Authorization header file under .evidence/dev/generated/keys/. It reports the path and never
prints the token. Task grants come from the configured Casework authority and are not static local
client attributes.
evidencectl access manages caller access for one local project:
| Command | State | Result |
|---|---|---|
evidencectl access policy add <policy> --question <question> | Creates access/policies/<policy>.yaml | Defines one or more repeated --question values for the next Evidence Gateway generation |
evidencectl access policy list | Reads access/policies/ | Lists the governed local policies and their questions |
evidencectl access client add <client> --policy <policy> --generate-local-key | Creates access/clients/<client>.yaml and .evidence/clients/<client>/private.jwk | Registers a local client for repeated --policy values with non-overlapping question sets |
evidencectl access client list | Reads access/clients/ | Lists local client status and policy membership |
evidencectl access client revoke <client> | Updates access/clients/<client>.yaml | Revokes the local client for the next issuer generation and removes .evidence/clients/<client>/, the client’s local private key |
For an institutional task exchange, author an optional taskGrant on the policy with its
kind, exact sourceIssuer, active requesterClients, and one bindings entry for each
question, subject role, and selector alternative. Each binding maps the selector’s complete field
set to verified access-token valueClaims. The compiler emits authenticated-grant origins and
binds the policy tag to the full grant semantics; it refuses revoked, unassigned, or incomplete
requester bindings. Create the requester with
evidencectl access client add <client> --policy <policy> --generate-local-key --grant-bootstrap-scope <scope>.
Use --grant-bootstrap-resource <URI> only if its issuer bootstrap resource differs from the
shared issuer owner’s default. The borrowed issuer must register that same key and bootstrap
binding for institutional exchange. A direct client omits both bootstrap flags.
For a portal that signs first-party context, create an active policy client with
--first-party-bootstrap-scope evidence:invoke --first-party-bootstrap-resource <Evidence resource> --first-party-issuer <issuer>.
The borrowed owner must register the same client key and bootstrap permission, and an exact
first_party exchange issuer. Its bootstrap registration carries no static Evidence requester
tags or audience; the signed context supplies those attributes for each request. The client
still needs an active Evidence policy assignment and cannot use a task-grant policy.
Public, reviewable local access configuration lives under access/. Owner-only private client keys
live only under .evidence/clients/. Generated issuer resources under .evidence/dev/generated/issuer/
are disposable.
Stop the local development session before adding or revoking a client. The next start validates the complete client and policy registry, then provisions it as one issuer generation. A policy change also requires a new Evidence Gateway generation.
The local access commands do not define production authority or production clients. Production
authority profiles remain in the deployment target’s governed governance.yaml. Production client
registrations remain in the deployment’s governed OAuth issuer. Files under access/ and
.evidence/ do not become production candidate inputs.
Use keygen, source suggest, request, verify, and audit for their documented authoring or
local inspection roles. Do not use a local request, local audit record, or disposable key as a
production candidate input.
Editor support
Section titled “Editor support”evidencectl tooling groups the two commands that serve an editor rather than a deployment.
| Command | Inputs | Result | Does not do |
|---|---|---|---|
evidencectl tooling editor [<project>] | Editable project directory, defaulting to the current directory | Writes the project-local schema mappings VS Code and Zed read, and reports all six managed files | Install an extension, change editor settings outside the project, or replace a file it did not write |
evidencectl tooling language-server | No arguments; speaks the Language Server Protocol over standard input and output | Reports Evidence Gateway authoring diagnostics for every document it indexes in the project, not only the open one | Open a socket, contact a source, read source values, or observe SQLite |
tooling editor writes six files into the project:
.evidence-editor/manifest.json.evidence-editor/schemas/project-marker.schema.json.evidence-editor/schemas/question.schema.json.vscode/extensions.json.vscode/settings.json.zed/settings.jsonCommit all six with the rest of the project. They are generated, nonsecret configuration matched to
the schemas the checks apply, and the .gitignore that evidencectl init writes excludes secrets/
and .evidence/ only. A later run refreshes exactly what an earlier run recorded writing. A managed
file someone has edited by hand stops the command, which names that file and changes nothing.
The mappings cover evidence-project.yaml and questions/*.yaml, the two document kinds a Rust type
stands behind. Sources, selectors, derivations, answer schemas, and fixtures carry no static schema;
the language server checks those.
A diagnostic in your editor carries the sentence evidencectl reports for the same input, because
both read one shared set of authoring checks. Fixing what the editor reports satisfies the command
line for that rule. The editor bounds a message at 1024 characters.
Base Registry Engine projects
Section titled “Base Registry Engine projects”The language server serves Evidence Gateway and Registry Relay projects. A Base Registry Engine
(BReg) project is neither, and it names its own project document registry.yaml. The editor tooling in this
page reports nothing about one, and starts no language server over one.
BReg publishes its authoring JSON Schemas as
registry-project.schema.json
and
registry-module.schema.json.
No command writes a mapping for them, so copy both into the BReg project and map them yourself in
.vscode/settings.json:
{ "yaml.schemas": { "./schemas/registry-project.schema.json": "registry.yaml", "./schemas/registry-module.schema.json": "modules/*/module.yaml" }}Related reference
Section titled “Related reference”The generated evidencectl syntax is published only after its exact source version receives a
recorded human review.