Files
ThothII/docs/contracts/workspace-evidence-v3.md
T

8.5 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.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: example/evidence
    patterns:
      - "**/*.md"
    max_bytes: 10485760
  policy:
    max_chunk_chars: 4000
    retain_published_generations: 3

Safe: example/evidence. Unsafe filesystem identities include /srv/evidence, another/evidence and example/evidence/../another because cross-namespace and traversal paths are not canonical. Legacy split-layout paths are rejected as noncanonical.

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.

At the connector boundary 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. Users enter the corresponding values through Workspace management; the backend stores them as authenticated ciphertext and materializes these files only for a runtime lease. Scalar S3 files are nonempty UTF-8 tokens without whitespace or NUL. Public docs, APIs, 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 workspace repository

All workspace namespaces live in one Git repository:

workspace-repository.git/
├── thoth-workspaces.yaml
├── example/
│   ├── workspace.yaml
│   └── evidence/...
└── another/
    └── workspace.yaml

The curator-owned root catalog thoth-workspaces.yaml uses the schema_version value 1 and the ordered workspaces list of {id, name, description?} entries. It is authoritative for workspace ID, name, description, and display order. The descriptor at <id>/workspace.yaml must match the catalog metadata exactly. Every catalog entry must have its descriptor at that same commit; catalog-only entries are invalid and reject the complete candidate revision.

Workspace source changes only through curator Git commit/push in a separate authoring clone, followed by an installation pull. The API never writes thoth-workspaces.yaml, <id>/workspace.yaml, <id>/schema/**, or <id>/evidence/**.

Registry revision and phase ownership

Relationship Contract
Revision identity The catalog blob, 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 catalog and descriptor blobs are unchanged.
Repository consumer ThothII fetches and validates a complete candidate, atomically activates it only on success, and never edits, commits, or pushes repository content.
Runtime secrets Workspace management returns configured/missing status only; decrypted values exist only for the lifetime of a diagnostic or runtime lease.
P1.1 Validates the lexical URI <id>/evidence and proves the declared filesystem root object is a Git tree at that same commit; it does not recursively inspect nested symlinks. Evidence materialization stays out of scope for P1.1.
P6 Owns commit-addressed materialization, realpath and recursive containment, nested-symlink checks, and race checks.

P1.1 performs no acquisition, extraction, preprocessing/indexing, embeddings, Qdrant writes, active-snapshot 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