7.8 KiB
Workspace Evidence v3 contract
This is the canonical public contract for the optional evidence object in a schema-v3
workspace descriptor. Evidence is optional: a valid v3 descriptor without it remains operational.
When present, evidence is strict: it contains source and a defaulted strict policy; every
source variant and the policy reject unknown keys.
Filesystem source
A filesystem source uses the exact URI workspace-content/<workspace.id>/evidence. patterns is
a nonempty list of unique, normalized relative POSIX globs. Its defaults are
patterns: ["**/*.md"] and max_bytes: 10485760.
Example: filesystem
evidence:
source:
type: filesystem
uri: workspace-content/example/evidence
patterns:
- "**/*.md"
max_bytes: 10485760
policy:
max_chunk_chars: 4000
retain_published_generations: 3
Safe: workspace-content/example/evidence. Unsafe filesystem identities include /srv/evidence,
workspace-content/another/evidence, and workspace-content/example/../another/evidence because
absolute, cross-namespace, and traversal paths are not canonical.
HTTP source
uris is a nonempty, unique list of canonical HTTP or HTTPS provenance identities. Each URI must
have no whitespace, control character, backslash, userinfo, query, or fragment. Public mode uses
authentication: none; signed mode uses authentication: signed_urls_file. Defaults are
authentication: none, connect_timeout_ms: 5000, read_timeout_ms: 30000,
max_bytes: 10485760, max_redirects: 5, allow_private_hosts: false, and
max_cache_bytes: 67108864. Public HTTP (authentication: none) uses the declared query-free
URIs directly and requires no Evidence credential file. Signed HTTP uses the installation file
contract below and preserves a mandatory one-to-one provenance mapping in declared-URI order.
Example: http
evidence:
source:
type: http
uris:
- https://evidence.example.invalid/report.md
authentication: signed_urls_file
connect_timeout_ms: 5000
read_timeout_ms: 30000
max_bytes: 10485760
max_redirects: 5
allow_private_hosts: false
max_cache_bytes: 67108864
policy:
max_chunk_chars: 4000
retain_published_generations: 3
The shown provenance URI is safe and query-free. An HTTP fragment identity such as
https://evidence.example.invalid/report.md#section is unsafe. Query-bearing and userinfo-bearing
HTTP identities are rejected; public documentation must not spell or publish a signed transport
URL.
S3 source
uri is a canonical s3:// identity with a valid bucket and no port, userinfo, query, or fragment.
endpoint_url, when present, is an origin-only HTTP(S) URL; region, when present, is nonblank.
Defaults are credentials: ambient, trusted_endpoint: false, allow_private_endpoint: false,
allow_insecure_endpoint: false, max_bytes: 10485760, max_objects: 10000, max_pages: 100,
and page_size: 1000 (and page size cannot exceed 1000). A custom endpoint requires
trusted_endpoint: true; an HTTP endpoint additionally requires allow_insecure_endpoint: true.
Endpoint-policy flags cannot be enabled without endpoint_url. Ambient S3
(credentials: ambient) uses the runtime provider chain and requires no Evidence credential file.
Static mode uses credentials: static_files, requires access-key and secret-key files together,
and permits an optional session-token file.
Example: s3
evidence:
source:
type: s3
uri: s3://example-evidence/curated/
credentials: static_files
trusted_endpoint: false
allow_private_endpoint: false
allow_insecure_endpoint: false
max_bytes: 10485760
max_objects: 10000
max_pages: 100
page_size: 1000
policy:
max_chunk_chars: 4000
retain_published_generations: 3
Safe: s3://example-evidence/curated/. Unsafe identities include
s3://Invalid_Bucket/evidence and s3://example-evidence/evidence#section. S3 userinfo and query
identities are rejected in prose and implementation; no credential-bearing example is published.
Policy and numeric domains
The strict policy defaults to max_chunk_chars: 4000 and
retain_published_generations: 3. Filesystem max_bytes; HTTP connect_timeout_ms,
read_timeout_ms, max_bytes, and max_cache_bytes; S3 max_bytes, max_objects, max_pages,
and page_size; and both policy values must be positive safe integers from 1 through
9007199254740991. HTTP max_redirects must be a nonnegative safe integer from 0 through
9007199254740991. S3 page_size has the stricter maximum of 1000.
Installation files
The namespace is the workspace ID uppercased with every - changed to _. All Evidence variables
hold file paths, never credential or signed-URL values.
| Mode | Variable | File contract |
|---|---|---|
| Signed HTTP | THT_WS_<NAMESPACE>_EVIDENCE_SIGNED_URLS_FILE |
Required for signed_urls_file; at most 1048576 bytes; nonempty UTF-8 JSON string array in declared-URI order; query-stripped identities must match uris one-to-one. |
| Static S3 pair | THT_WS_<NAMESPACE>_EVIDENCE_ACCESS_KEY_FILE and THT_WS_<NAMESPACE>_EVIDENCE_SECRET_KEY_FILE |
Required together for static_files; each file is at most 65536 bytes. |
| Static S3 session | THT_WS_<NAMESPACE>_EVIDENCE_SESSION_TOKEN_FILE |
Optional, valid only with the required access/secret pair, and at most 65536 bytes. |
Every variable is an absolute path to a readable regular file whose resolved target is strictly below one of the roots configured by THT_WORKSPACE_SECRET_ROOTS. Scalar S3 files are nonempty
UTF-8 tokens without whitespace or NUL. Public docs, exports, and rendered YAML never expose file contents. changeme, replace-me, YOUR_SECRET, <secret>, access-key-looking strings, and any
credential-bearing or query-bearing URI are forbidden as public placeholder values.
One shared registry repository
All workspace namespaces live in one Git repository:
registry.git/
├── workspaces/
│ ├── example.yaml
│ └── another.yaml
├── workspace-content/
│ ├── example/evidence/...
│ └── another/evidence/...
└── workspace-docs/
├── example/{contract.env.example,README.md}
└── another/{contract.env.example,README.md}
Curators change only workspace-content/<id>/evidence/** through a normal clone. The API publishes
only workspaces/<id>.yaml and
workspace-docs/<id>/{contract.env.example,README.md}. It never writes Evidence source bytes.
Registry revision and phase ownership
| Relationship | Contract |
|---|---|
| Revision identity | The descriptor blob and filesystem Evidence root tree are checked at the same 40-hex Git commit. |
| Content-only revision | An Evidence-only commit changes authoritative revision.commit even when the descriptor blob is unchanged. |
| Browser | Create and edit flows preserve and show a read-only Evidence summary. |
| Export | Export remains exactly manifest, descriptor, contract, and README; it excludes Evidence bytes. |
| P1 | Validates the lexical URI and proves the declared filesystem root object is a Git tree at that same commit; it does not recursively inspect nested symlinks. |
| P6 | Owns commit-addressed materialization, realpath and recursive containment, nested-symlink checks, and race checks. |
P1 performs no acquisition, extraction, preprocessing/indexing, embeddings, Qdrant writes, ACTIVE publication, retention, or GC.
Operator validation
After the runtime configuration is rendered or acquired, validate it with the exact per-command option ordering:
tht config check -c <path>
Stop after validation. P2/P6 later owns preprocessing and materialization.
Acceptance states
These gates are independent and are not implied by this documentation contract.
automated integration: PENDING manual acceptance: PENDING