Skip to content
Registry StackDocsv0.38.0

Evidencectl workflow reference

View as Markdown

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.

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.

CommandInputsResultDoes not do
evidencectl check <project>Editable projectReports authoring completeness and field-addressed findingsClaim deployment closure, run fixtures, resolve secrets, or contact a dependency
evidencectl check <project> --target <target>Editable project and one explicit targetAdds the target’s governance, runtime structure, public keys, source connections, and governed-bundle validationRequire target-host paths or secrets to exist, run fixtures, or contact a dependency
evidencectl check <project> --target <target> --productionEditable project and one explicit production or evidence-grade targetRefuses incomplete deployment closure under that target’s own assurance profileSelect a target, upgrade its profile, or prove live readiness
evidencectl explain <project> [--target <target>]Editable project and optional explicit targetApplies the same offline authoring validation, then reports status, findings, revision, and the authored inventory; includes target governance only when selectedContact sources or expose secret and subject values
evidencectl package <project> --target <target> --output <new-package>Editable project and one explicit production targetCreates one closed package with SHA256SUMS; runtime remains in the targetOverwrite 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 governancePrivately compiles the project, then uses runtime bundle-check and bundle-evaluateStart HTTP, call a source, or write a production audit entry
evidencectl test <editable-project> --target <deployment-target> --explainThe same, and asks each evaluation to explain itselfRelays each fixture’s stage trace beside its step, or as that fixture’s trace field under --format jsonPrint a response, fact, derived, or selector value, or explain a served request
evidencectl doctor --runtime-config <absolute-file>Runtime file on its target hostRuns the runtime-owned startup dependency preflight without opening the public listenerSend an Evidence request or establish that a fixture passed
evidencectl artifact inspect <target>Deployment target whose runtime names the installed packageInspects artifact custody without contacting dependenciesEstablish 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.

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.

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 governance metadata in every question.
  • <target>/governance.yaml with bundle-owned fields for one environment.
  • <target>/runtime.yaml with 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.

evidencectl init requires a destination and exactly one authoring source:

Terminal window
evidencectl init <directory> --openapi <path-or-https-url> --profile local
evidencectl init <directory> --transport sqlite-extract --profile local

OpenAPI 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:

CommandStateResult
evidencectl access policy add <policy> --question <question>Creates access/policies/<policy>.yamlDefines one or more repeated --question values for the next Evidence Gateway generation
evidencectl access policy listReads access/policies/Lists the governed local policies and their questions
evidencectl access client add <client> --policy <policy> --generate-local-keyCreates access/clients/<client>.yaml and .evidence/clients/<client>/private.jwkRegisters a local client for repeated --policy values with non-overlapping question sets
evidencectl access client listReads access/clients/Lists local client status and policy membership
evidencectl access client revoke <client>Updates access/clients/<client>.yamlRevokes 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.

evidencectl tooling groups the two commands that serve an editor rather than a deployment.

CommandInputsResultDoes not do
evidencectl tooling editor [<project>]Editable project directory, defaulting to the current directoryWrites the project-local schema mappings VS Code and Zed read, and reports all six managed filesInstall an extension, change editor settings outside the project, or replace a file it did not write
evidencectl tooling language-serverNo arguments; speaks the Language Server Protocol over standard input and outputReports Evidence Gateway authoring diagnostics for every document it indexes in the project, not only the open oneOpen 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.json

Commit 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.

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"
}
}

The generated evidencectl syntax is published only after its exact source version receives a recorded human review.