Skip to content

Branding (logos/colors), dashboard updates, and add model/provider explore page#121

Merged
13rac1 merged 17 commits into
mainfrom
brand-and-dashboard
Jun 30, 2026
Merged

Branding (logos/colors), dashboard updates, and add model/provider explore page#121
13rac1 merged 17 commits into
mainfrom
brand-and-dashboard

Conversation

@13rac1

@13rac1 13rac1 commented Jun 29, 2026

Copy link
Copy Markdown
Owner

We needed a logo/color scheme, more details on the dashboard, and the ability to easily run model attestation/inference tests.

  • Created branding with logo, colors, and description.
  • Applied branding to the teep serve dashboard, then expanded the features to increase information clarity (still more to go, but this is good enough to ship)
  • Expanded provider specific model data structs to capture/display detailed information
  • Created a "teep - explore" page to run attestation and inference for all supported models/providers for testing/evaluation: http://localhost:8337/explore

I am specifically not using external JS libraries or external assets at this time.

Main Dashboard:
image

Explore:
image

Example Failure on Venice due to #113
image

@github-actions

This comment has been minimized.

13rac1 and others added 15 commits June 29, 2026 14:25
Create a logo for teep and rework the live dashboard around it,
dependency-free (inline SVG/CSS/JS, system fonts only).

Brand
- Mark is a "held prompt": a rounded cradle (mint guards = teep)
  holding a chevron (light = your prompt, the thing that stays yours).
  Protective, not a checkpoint — a guard, not a gate.
- docs/brand/ ships the mark, dark/light logo lockups, a palette +
  construction guide, and a dashboard preview.
- README header uses <picture> + prefers-color-scheme so the dark-first
  lockup swaps to a light variant on GitHub's light theme.

Dashboard
- New "enclave graphite" palette and monospace-forward identity,
  off the generic GitHub-dark default.
- Live attestation seal hero: the mark inside a factor-coverage ring
  that fills and recolors with posture (sealed / partial / blocked / idle).
- Per-model factor drill-down grouped by tier, tier coverage bars,
  model filter, copy-to-clipboard for the base URL and model ids,
  and a client-side request-rate sparkline.
- buildDashboardData now ships per-factor and per-tier data
  (dashFactor / dashTier) that the old page discarded.
- Reduced-motion respected, responsive to mobile, visible focus.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Test the dashboard index, metrics, and SSE endpoints with HTML
structure validation via golang.org/x/net/html parsing. Also fix
exhaustive lint in tier rollup switch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Moves the ~700-line raw string constant into dashboard.html and loads
it via //go:embed. The Go file drops from 1139 to 443 lines, and the
HTML gets proper syntax highlighting and editor tooling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New /test page lets users trigger attestation and E2EE inference tests
from the browser. Models are fetched from /v1/models on page load, with
Attest and Infer buttons on each model card. Attestation results show
the full factor/tier breakdown; inference loops back through the proxy's
own ServeHTTP to prove end-to-end functionality.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the union modelEntry (which mixed NEAR and Tinfoil fields) with
properly typed per-provider structs: nearModelEntry, chutesModelEntry,
veniceModelEntry, tinfoilModelEntry, and phalaModelEntry. Switch Chutes
and Venice model listers from json.Unmarshal to jsonstrict.UnmarshalWarn
for schema drift detection. Add validatingModelLister wrapper for
Tinfoil and Phalacloud providers that use genericModelLister.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Display context window, type, quantization, owner, capabilities,
modalities, and description in model cards using data already flowing
through /v1/models. All metadata renders conditionally based on what
each provider includes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mark NEAR fields that aren't present on all model entries (quantization,
hugging_face_id, is_ready, datacenters, openrouter) with omitempty so
jsonstrict does not report them as missing. Add context_length to
veniceModelEntry to match Venice's actual API schema.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Older Chutes models omit context_length, modalities, quantization,
features, and permission. Tag these fields omitempty so jsonstrict
does not report them as missing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tinfoil context_window and NEAR max_output_length are not present on
all model entries. The top-level modelsResponse object field is absent
from Phalacloud responses. Tag all three with omitempty.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pinned handlers (nearcloud, neardirect) call BuildReport without
setting Inapplicable, causing nvswitch_binding and sigstore_code_verified
to incorrectly block NEAR models. Default to the standard inapplicable
set when callers pass nil instead of requiring every call site to
explicitly provide it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Defense in depth: the nil-default safety net still applies
DefaultInapplicableFactors, but now emits a warning so the
programming error is visible in logs rather than silently corrected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
De-duplicate CSS and JS between dashboard and explore (formerly test) pages
using Go html/template partials. Rename /test to /explore to better reflect
the user-facing purpose of the page.

Key changes:
- Extract shared CSS into templates/_base_css.html and shared JS into
  templates/_base_js.html using {{define}}/{{template}} composition
- Move HTML files into templates/ directory, serve via template.ExecuteTemplate
- Rename test → explore: routes, handlers, types, template names
- Add allow-fail factor yellow styling (warn class) distinct from enforced
  failures (red) in both factor lists and tier bars
- Add provider metadata (pinned TLS, E2EE capable) pills on explore page
  provider group headers via template-injected JSON
- Add E2EE active/capable/no distinction in explore inference results
- Add report timestamp display (relative time) after attestation
- Fix blocked pill CSS class collision (.block layout vs .pill.block)
- Add warned tier bar segment and dashTier.Warned field for allowed failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix double-escaping in tierBars: remove redundant esc() call on tier
  labels that were already escaped by the fallback path.
- Add r.ok checks to all fetch() calls in explore.html so HTTP errors
  surface as "HTTP 4xx" messages instead of JSON parse failures.
- Remove second-level card expand on explore model cards; card-body
  (pills, buttons, results) is now always visible when the provider
  group is expanded, matching dashboard behavior.
- Replace json.Unmarshal with jsonstrict.UnmarshalWarn in explore.go
  to match the project's strict JSON parsing standard.
- Delete dead FetchRekorProvenances (no production callers); update
  test to use FetchRekorProvenancesForPolicy with nil policy.
- Replace raw strings.Cut with resolveModel + cacheModelFor in
  loopbackInfer E2EE cache lookup for consistency with inference path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@13rac1 13rac1 force-pushed the brand-and-dashboard branch from debae91 to e370ddf Compare June 29, 2026 21:25
@github-actions

This comment has been minimized.

Cover the explore page success paths that were at 0-57% coverage:
loopbackInfer (0% → 92%), handleExploreAttest (52% → 86%),
handleExploreInfer (43% → 78%), handleExplorePage (57% → 64%).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a first-party, self-contained UI layer to teep serve (branding + dashboard overhaul) and introduces an “Explore” page for manually triggering provider/model attestation and a small inference smoke test.

Changes:

  • Introduce shared embedded HTML templates + shared base CSS/JS for the serve dashboard UI.
  • Add /explore UI plus POST endpoints to run on-demand attestation and a loopback inference test.
  • Expand model listing schema validation across providers (jsonstrict-based) and enrich dashboard attestation data (per-factor + per-tier rollups).

Reviewed changes

Copilot reviewed 24 out of 27 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
README.md Adds brand logo lockup to README header.
internal/proxy/templates/explore.html New Explore UI: model listing + “Attest/Infer” actions.
internal/proxy/templates/dashboard.html New dashboard UI template with richer attestation/traffic visualization.
internal/proxy/templates/_base_js.html Shared client JS helpers (escaping, factor/tier rendering, time formatting).
internal/proxy/templates/_base_css.html Shared base styling + brand palette/tokens.
internal/proxy/templates.go Embeds/parses templates via embed.FS and template.ParseFS.
internal/proxy/proxy.go Registers /explore and swaps Phala/Tinfoil model listers to validating wrappers.
internal/proxy/explore.go Implements Explore handlers + loopback inference logic.
internal/proxy/explore_internal_test.go Tests Explore page rendering and infer/attest endpoints.
internal/proxy/dashboard.go Switches index handler to template rendering + adds per-factor/per-tier data.
internal/proxy/dashboard_internal_test.go Adds HTML rendering + inlined JSON validation tests for dashboard.
internal/provider/venice/models.go Uses jsonstrict schema + capability filtering for Venice models.
internal/provider/venice/models_test.go Updates Venice model fixtures for expanded schema coverage.
internal/provider/models.go Adds provider-specific schemas + validating model lister wrapper and validators.
internal/provider/models_test.go Updates NEAR fixtures and adds validating model lister test.
internal/provider/chutes/models.go Uses jsonstrict schema + confidential_compute filtering for Chutes models.
internal/provider/chutes/models_test.go Updates Chutes model fixtures for expanded schema coverage.
internal/config/update.go Marks neardirect default as E2EE-capable.
internal/config/config.go Sets neardirect env override to enable E2EE by default.
internal/config/config_test.go Adjusts neardirect E2EE assertion message for clarity.
internal/attestation/report.go Changes nil Inapplicable semantics to apply a default map + logs warning.
internal/attestation/rekor.go Removes deprecated FetchRekorProvenances helper.
internal/attestation/rekor_test.go Updates tests to use FetchRekorProvenancesForPolicy.
docs/brand/teep-mark.svg Adds brand mark asset.
docs/brand/teep-logo.svg Adds dark logo lockup asset.
docs/brand/teep-logo-light.svg Adds light logo lockup asset.
docs/brand/README.md Adds brand guidelines and usage instructions.

Comment thread internal/proxy/proxy.go
Comment thread internal/proxy/explore.go
Comment on lines +93 to +106
prov, upstreamModel, ok := s.resolveModel(req.Model)
if !ok {
http.Error(w, fmt.Sprintf("unknown model: %q", req.Model), http.StatusBadRequest)
return
}

report, _ := s.fetchAndVerify(ctx, prov, upstreamModel)
if report == nil {
http.Error(w, "attestation fetch failed; see server logs", http.StatusBadGateway)
return
}

s.cache.Put(prov.Name, upstreamModel, report)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha! I noticed this happening, but planned to debug later.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1829660. handleExploreAttest now applies CacheKeySuffix to the context before fetchAndVerify and uses cacheModelFor for cache.Put.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed
image

Comment thread internal/proxy/explore.go
Comment on lines +135 to +139
if _, _, ok := s.resolveModel(req.Model); !ok {
http.Error(w, fmt.Sprintf("unknown model: %q", req.Model), http.StatusBadRequest)
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1829660. loopbackInfer E2EE lookup now applies CacheKeySuffix before the cache.Get so it finds the report under the correct suffixed key.

Comment thread internal/proxy/explore.go
Comment on lines +175 to +194
result := rec.Result()
defer result.Body.Close()
respBody, _ := io.ReadAll(result.Body)

if result.StatusCode != http.StatusOK {
// Try to parse as a verification report (502 blocked response).
var report attestation.VerificationReport
if err := json.Unmarshal(respBody, &report); err == nil && report.Provider != "" {
return exploreInferResponse{
Model: model,
Blocked: true,
Report: &report,
Error: fmt.Sprintf("attestation blocked (HTTP %d)", result.StatusCode),
}
}
return exploreInferResponse{
Model: model,
Error: fmt.Sprintf("HTTP %d: %s", result.StatusCode, bytes.TrimSpace(respBody)),
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 1829660. Response body read is now capped to 1 MB via io.LimitReader, and echoed error bodies are truncated to 512 bytes.

Comment thread internal/provider/models.go
Comment thread internal/attestation/report.go
Apply CacheKeySuffix in handleExploreAttest and loopbackInfer E2EE
lookup so cache keys match the main proxy path (e.g. model@domain for
tinfoil direct). Cap loopback response body read to 1 MB and truncate
error messages to 512 bytes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Code Metrics Report

main (42f0339) #121 (37257de) +/-
Coverage 87.9% 87.9% -0.1%
Test Execution Time 35s 36s +1s
Details
  |                     | main (42f0339) | #121 (37257de) |  +/-  |
  |---------------------|----------------|----------------|-------|
- | Coverage            |          87.9% |          87.9% | -0.1% |
  |   Files             |             86 |             87 |    +1 |
  |   Lines             |          10286 |          10416 |  +130 |
+ |   Covered           |           9048 |           9157 |  +109 |
- | Test Execution Time |            35s |            36s |   +1s |

Code coverage of files in pull request scope (87.3% → 87.2%)

Files Coverage +/- Status
internal/attestation/rekor.go 92.0% -0.2% modified
internal/attestation/report.go 96.2% +0.0% modified
internal/config/config.go 95.9% 0.0% modified
internal/config/update.go 89.7% 0.0% modified
internal/provider/chutes/models.go 89.2% 0.0% modified
internal/provider/models.go 76.0% -11.8% modified
internal/provider/venice/models.go 85.1% 0.0% modified
internal/proxy/dashboard.go 91.6% +3.1% modified
internal/proxy/explore.go 84.0% +84.0% added
internal/proxy/proxy.go 76.7% +0.2% modified
internal/tlsct/checker.go 89.3% -1.7% affected

Reported by octocov

@13rac1 13rac1 merged commit fac444f into main Jun 30, 2026
1 check passed
@13rac1 13rac1 deleted the brand-and-dashboard branch June 30, 2026 16:21
@mikeperry-tor mikeperry-tor requested a review from Copilot June 30, 2026 18:40
@13rac1 13rac1 removed the request for review from Copilot June 30, 2026 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants