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

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