Skip to content

Query an app's evidence

Answer "what has this app done, and who approved it?" with one query. The evidence index returns every category — prompts, models, artifacts, tests, promotions, deployments, data access — in a single response, in under ten seconds.

Preconditions

  • A running platform and kubectl access to tend-system.
  • An app with some history (created, iterated, ideally promoted).

Steps

1. Reach the evidence & estate API

kubectl -n tend-system port-forward svc/evidence-estate-api 18082:8080 &

2. Run the one query

time curl -s http://localhost:18082/apps/expense-helper/evidence | jq 'keys'

Expect every category in one response, and wall-clock under 10 s (SC-003): app, owner, purpose, aiActTriage, dataScopes, prompts, models, artifacts, tests, promotions, deployments, dataAccess, tier1Posture, completeness, provenance (plus pipelines, policy and vulnerabilities once the app has data for them).

3. Pull out what you need

EV=http://localhost:18082/apps/expense-helper/evidence

# Prompts and models (assembled from the Harbor attestations)
curl -s "$EV" | jq '{prompts, models}'

# Approvals: who approved which promotion, and when
curl -s "$EV" | jq '.promotions[] | {prUrl, decision, approver, decidedAt}'

# Deployments per environment (from Argo CD history)
curl -s "$EV" | jq '.deployments'

# Data access decisions — allow AND deny — from the gateway log
curl -s "$EV" | jq '.dataAccess[] | {source, decision, reason, at}'

dataAccess is bounded to the most recent page by default; ?dataAccessLimit=<n> widens it.

4. Read the completeness and provenance maps — always

curl -s "$EV" | jq '{completeness, provenance}'
  • completeness has one entry per category: complete, partial, or unavailable. Partial results are never presented as complete — treat an empty category marked unavailable as "source unreachable", not as "nothing happened".
  • provenance names the authoritative source that served each category (for example harbor-attestations, app-cr+gitea, argocd, data-gateway). Hand-entered data is not a legal value.

5. Query the estate

curl -s http://localhost:18082/estate \
  | jq '.apps[] | {name, aiActTriage, cost, suspended}'
curl -s "http://localhost:18082/estate?aiActTriage=true" | jq '.apps[].name'
curl -s "http://localhost:18082/estate?costState=suspended" | jq '.apps[].name'

Verify it worked

The query returned in under 10 s, every category key is present, and completeness explains any gap explicitly. If no category could be assembled the API returns 503 instead of a silently empty record.

When the evidence page is not enough

For full lifetime data-access history, page the gateway's query API directly (platform OIDC token required; records newest-first, follow nextCursor):

kubectl -n tend-system port-forward svc/data-gateway 18081:8080 &
curl -s -H "Authorization: Bearer $PLATFORM_TOKEN" \
  "http://localhost:18081/v1/logs?app=tend-system/expense-helper&limit=1000" \
  | jq '{count: (.records|length), nextCursor}'

Response shapes and all query parameters are in the evidence & estate API reference and the data gateway API reference; why the index assembles rather than stores is in The evidence chain.