189 lines
8.5 KiB
Markdown
189 lines
8.5 KiB
Markdown
# 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
|
|
|
|
```yaml
|
|
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
|
|
|
|
```yaml
|
|
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
|
|
|
|
```yaml
|
|
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:
|
|
|
|
```text
|
|
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:
|
|
|
|
```sh
|
|
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
|