how are quests created? what basis, criteria?

In Treads, quests are implemented as the Daily Species Hunt (engine located in lib/hunt.ts).
Here is how they are generated, their structural basis, and the criteria used to fulfill them:
1. How Quests Are Created (Deterministic Generation)
Quests are generated entirely client-side and deterministically—no server API call or database seed is needed:
- Date Seeding: The app takes the user’s local calendar date string in
YYYY-MM-DDformat viatoLocaleDateString('en-CA'). - FNV-1a Hashing: The date string is hashed using a 32-bit FNV-1a hash algorithm (
hashDateString): - Catalog Indexing: The hash selects a template index via modulo arithmetic (
hash % CHALLENGE_CATALOG.length). - Quest Instantiation:
getDailyHunt()constructs aDailyHuntobject with unique target IDs tied to the date (e.g.,id: "hunt-2026-10-10"). Every player on the same calendar day receives the exact same challenge.
2. The Basis & Structure (Challenge Catalog)
The challenges are built from a catalog of 14 curated ecological objectives designed to encourage varied environmental observation (looking up at the canopy, checking the ground, listening for birds, inspecting flowers):
Taxonomic Categories (OrganismKind)
Target kinds map to:
'tree''flower''plant''bird''insect''fungus''other'
Criteria & Pairing Archetypes
Each challenge specifies 1 or 2 target criteria with required observation counts (1 or 2):
| Quest Title | Target Criteria | Intent / Ecological Theme |
|---|---|---|
| Canopy & Ground Cover | 1 Tree + 1 Insect | Looking high and low along the forest strata |
| Botanical Duo | 1 Wild Plant + 1 Flower | Flora diversity along the trail |
| Feathers & Foliage | 1 Bird + 1 Tree | Avian tracking and woodland trees |
| Pollinator Patrol | 1 Flower + 1 Insect | Observing pollinator relationships |
| Forest Floor Mycota | 1 Fungus + 1 Plant | Decomposing organic matter & ground cover |
| Shade & Spores | 1 Fungus + 1 Tree | Tree brackets, moss, and shaded spots |
| Winged Companions | 1 Bird + 1 Insect | Airborne wildlife |
| Arboreal Study | 2 Trees | Distinguishing tree bark & leaf varieties |
| Avian Watch | 2 Birds | Bird observation |
| Micro-Fauna Explorer | 2 Insects | Ground & undergrowth arthropods |
| Wild Meadow Search | 2 Flowers | Wildflower patches |
| Green Tapestry | 2 Plants | Ferns, undergrowth, and foliage |
| Full Nature Spectrum | 1 Plant + 1 Bird | Combining flora with fauna |
3. Evaluation & Completion Criteria
Progression is calculated via evaluateHuntProgress(hunt, entries) using these rules:
- Confirmation Requirement: Only entries marked with
status === 'confirmed'and having valid identification data count. - Same-Day Local Timestamp: The specimen must have been recorded between
00:00and23:59on the challenge date (hunt.date). - Cross-Session Continuity: Encounters count across all walks completed on that calendar day (the user does not have to find everything in a single walk).
- No Double-Counting: Each confirmed specimen is reserved via an
assignedEntryIdsset so one find cannot satisfy multiple targets. - Completion Trigger: Once all target counts are satisfied (
targetProgress.every(tp => tp.completed)):- Opens the
DailyHuntCelebrationDialog. - Plays a chord arpeggio chime via
playHuntChime. - Triggers physical haptic pulses on mobile via
triggerHuntWinHaptic.
- Opens the
4. Where Quests Appear in the App
- Active Walk HUD: A live pill (
DailyHuntHudPill) incomponents/walk/walk-hud.tsxtracks progress (e.g.Hunt: 1/2) while recording a walk. - Collection / Field Guide: A hero banner (
DailyHuntCard) at the top ofapp/collection/page.tsxandapp/walk/page.tsxdisplays today's title, description, and status pips.
The current quest system (lib/hunt.ts) provides a clean, privacy-respecting deterministic foundation, but it has several clear limitations:
- Coarse taxonomic scope: Targets are limited to 7 broad buckets (
tree,insect,bird,flower,plant,fungus,other). - Context-blind: It asks for the same things regardless of whether it's freezing winter, peak spring bloom, dawn, dusk, urban pavement, or a dense pine forest.
- Single-action focus: Every quest simply requires snapping a photo and confirming a category. There is no sensory, spatial, or observational depth.
- Short rotation pool: Only 14 templates repeating cyclically via date hashing.
Here is how you can elevate quests into rich, captivating naturalist field missions:
1. Seasonal & Phenological Awareness (Calendar & Season Rules)
Nature changes dramatically across seasons. Instead of a single static pool of 14 templates, bucket challenges by season and month:
- Spring (Sprouting & Migrations): "The Early Flush" — Find emerging leaf buds or early spring ephemeral wildflowers; record an arriving songbird.
- Summer (Pollination & Canopy): "The Pollination Highway" — Spot an insect on a flowering blossom; identify a broadleaf tree in full canopy.
- Autumn (Fruiting & Decomposers): "Seed & Spores" — Discover bracket fungi on rotting wood and a plant displaying seeds, nuts, or berries.
- Winter (Bark & Evergreens): "Winter Silhouettes" — Identify an evergreen conifer; study and record deciduous bark texture or lichens.
2. Multi-Sensory & Journaling Objectives
Treads already records audio notes (Note), transcriptions, and telemetry. Quests can celebrate field craft rather than just photo identification:
- Soundscapes: "Avian Chorus" — Capture an audio recording of birdsong or wind rustling in the canopy alongside an identified bird or tree.
- Observational Field Notes: "The Naturalist's Pen" — Add a descriptive note detailing the habitat or organism behavior (e.g., "Noting where it was found").
- Macro vs. Habitat: "Micro & Macro" — Take a close-up detail shot of bark, moss, or veins, plus a wide landscape/specimen shot.
3. Personalization & Life List Integration
Using the local Dexie database (lib/db.ts), quests can react to the user’s personal collection history:
- First Encounter (Life List Expander): "New Horizon" — Identify any species not yet logged in your field collection.
- Taxon Deep Dive: "Family Portrait" — If a user already has an Oak in their collection, suggest finding another member of Fagaceae or a complementary understory shrub.
- Revisitation & Phenology: "Check the Grove" — Revisit a location where an organism was recorded over 30 days ago to observe seasonal changes.
4. Telemetry & Movement-Linked Quests
Tie quests into the walk session and GPS tracking (Walk):
- Spatial Diversity: "Transect Survey" — Record 2 distinct organisms at least 500 meters apart along your track.
- Pedestrian Loop Quests: "The 2 km Circuit" — Use the ORS route loop generator (
/api/route) to complete a 2 km walk while identifying at least 3 species. - Pacing & Mindfulness: "Slow Explorer" — Record at least 1 find on a walk lasting 20+ minutes.
5. Tiered Objectives (Base vs. Stretch Goals)
Instead of a binary complete/incomplete state, offer tiers so casual walkers aren't discouraged while avid naturalists are rewarded:
This ensures someone taking a 5-minute stroll around the block can still participate and earn a badge, while longer expeditions have room for mastery.
6. AI-Curated Naturalist Prompts (with Privacy & Offline Fallback)
Gemini (already integrated via @google/genai in app/api/identify/route.ts) could generate poetic, ecologically grounded daily prompts on request:
- Instead of "Find 1 tree and 1 insect", the prompt could be:
"The Understory Network: Notice how fallen deadwood shelters small life. Look for decomposers like bracket fungi or beetles near decaying logs."
- Gemini can also provide loose keyword/tag matching (e.g., identifying whether a candidate is an "evergreen", "pollinator", "raptor", or "succulent") rather than relying purely on the broad
kindenum.
Recommended First Steps to Upgrade the System
| Priority | Feature | Complexity | Impact |
|---|---|---|---|
| Quick Win | Expand catalog & add Seasonal Pools in lib/hunt.ts (24–36 diverse templates keyed to season/month). | Low | High — Immediately prevents repetitive daily challenges. |
| Medium | Life List Novelty Check (isNewSpecies: boolean) in evaluateHuntProgress. | Medium | High — Gives players a sense of RPG-like discovery progression. |
| Medium | Audio / Note Objectives by passing Note[] into the hunt evaluation engine. | Medium | High — Incentivizes using voice journaling. |
| Advanced | Distance & Telemetry Criteria tied to walk.distance and track points. | High | Medium — Great for runners and trail hikers. |
Seasonal quests and richer, more engaging field challenges have been added to the hunt engine and UI.
What Changed
1. Seasonal Quest Catalogs (lib/hunt.ts)
Replaced the static 14-item rotation with 32 phenologically authentic challenges partitioned across the 4 seasons:
- Spring (
SPRING_CATALOG): Focuses on vernal migrations, songbird territory calls, spring ephemerals, emerging pollinators, wind-borne catkins, and tender understory shoots. - Summer (
SUMMER_CATALOG): Focuses on dense broadleaf canopy, sunny meadow pollinators, thermal-soaring raptors, summer wildflowers, and deep woods bracket fungi. - Autumn (
AUTUMN_CATALOG): Focuses on carotenoid foliage change, fungal flushes on nurse logs, seed/acorn cache gatherers, flowering ivy pollinators, and leaf-litter arthropods. - Winter (
WINTER_CATALOG): Focuses on evergreen needle identification, mixed winter foraging flocks, bark lichens, cold-hardy rosettes, winter berries, and architectural deciduous silhouettes.
The helper getSeasonForDate(dateStr) determines the season from the calendar date without timezone drift, feeding the deterministic FNV-1a hash generator.
2. Engaging Naturalist Depth
Each challenge now includes:
- Field Lore Tips (
fieldTip): Practical naturalist observation techniques explaining where and how to look (e.g., watching south-facing stream banks, checking decaying nurse logs, inspecting bark crevices). - Difficulty Tiers (
difficulty): Categorized asGentle,Moderate, orExplorer. - Descriptive Targets (
HuntTarget.label): Contextual objectives like "Cap Mushroom or Bracket", "Songbird / Perched Avian", "Litter Arthropod", or "Seed-Bearing Wild Flora" instead of generic single-word labels.
3. UI Enhancements
- Hero Hunt Card (
DailyHuntCard):- Displays a seasonal tag with an adaptive icon (
Leaf,Sun,Wind,Snowflake) and difficulty indicator. - Adds a Field Lore callout box with a
Compassicon highlighting observation wisdom. - Retains visual progress pips and completion tracking.
- Displays a seasonal tag with an adaptive icon (
- Active Walk HUD (
DailyHuntHudPill):- Shows the season badge, difficulty rating, and field tip snippet directly within the HUD dropdown while walking.
- Celebration Dialog (
DailyHuntCelebrationDialog):- Awards a season-specific stamp (e.g.,
AUTUMN NATURALIST) upon fulfilling the day's field criteria.
- Awards a season-specific stamp (e.g.,
Verification
- Ran the test suite in
scripts/test-hunt-engine.ts:- Verified date determinism, midnight rollover, and progress evaluation.
- Verified seasonal routing across Spring (
2026-04-15), Summer (2026-07-20), Autumn (2026-10-10), and Winter (2027-01-15).
- Ran
tsc --noEmit: 0 type errors.
The .gitignore file has been configured, all working files staged and committed, and the git working tree is now clean.
Summary of Actions Taken:
- Configured
.gitignore:- Added standard Next.js, Node, TypeScript, and certificate patterns.
- Configured exclusion rules for local tool metadata, logs, and agent artifacts (
.entire/,.opencode/,.agents/,.fallow/,.temp/). - Retained project-specific spec rules (
DECISIONS.md,PRD.md).
- Staged & Committed All Changes:
- Committed with message:
feat: seasonal quests, hairline figures, and frontend enhancements(af8a60b). - Included seasonal hunt upgrades in
lib/hunt.tsand UI components incomponents/hunt/. - Included Hairline isometric figures, garden elements, map workers, and navigation components.
- Committed with message:
- Working Tree Status:
nothing to commit, working tree cleanon branchfeat/frontend.
Yes, the AI agents and inference pipelines in Treads are exceptionally well-guarded. The app implements defense-in-depth across five distinct layers: abuse prevention, harm mitigation, hallucination defense, privacy protection, and offline resilience.
1. Abuse & Quota Guardrails (Cost & Resource Protection)
All AI and external API endpoints are gated by checkRateLimit():
- Dual-Engine Limiting: Uses Upstash Redis with a sliding window in production, automatically falling back to an in-memory token bucket (
MemoryRateLimiter) in development or if Redis is unreachable. - Granular Daily Quotas (
ENDPOINT_QUOTAS):/api/identify: 30 calls/day per IP (Google Generative AI Vision)/api/facts: 60 calls/day per IP (Wikipedia + Google AI)/api/walk/dispatch: 40 calls/day per IP (Gemma naturalist chronicler)/api/transcribe: 30 calls/day per IP (ElevenLabs Scribe STT)/api/speak: 40 calls/day per IP (ElevenLabs TTS)/api/route: 40 calls/day per IP (OpenRouteService loop generation)
- Standardized RFC Headers: Rejected requests return HTTP
429 Too Many RequestswithX-RateLimit-*andRetry-Afterheaders.
2. Safety & Harm Prevention (Edibility & Misidentification)
Outdoor nature identification carries unique safety liabilities (e.g., users eating poisonous wild mushrooms or plants based on AI advice). The app implements strict guardrails:
- Regex Scrubber for Edibility & Toxicity (
lib/facts-safety.ts):Any synthesized fact matching culinary, foraging, recipe, medicinal, or toxicity terms is rejected before it can reach the user. - Inanimate Object & Human Portrait Refusal Gate (
app/api/identify/route.ts): The vision prompt explicitly instructs the model to detect non-living objects (mugs, bicycles, cars, rocks, buildings) and human portraits, returningisLivingOrganism: falsewith an educational explanation instead of hallucinating species candidates. - Anti-Hallucination Ecological Constraints (
app/api/walk/dispatch/route.ts): The walk dispatch agent is strictly constrained: "If there are NO direct known ecological relationships... return an empty array []. NEVER invent or hallucinate fictional relationships." - Degeneration & Tokenizer Artifact Detector (
isGarbageOrDegenerate): Detects and drops token repetition loops, runaway hyphenations, and prompt template leaks (e.g.,ueff_,<eos>,[PAD]).
3. Grounding & External Verification
- Wikipedia Taxon Verification (
app/api/identify/route.ts): Every species candidate produced by the vision model is cross-checked against the Wikipedia Action API (verifyWikipediaTaxon) to verify that the taxon exists as an authentic, documented biological entity. - Sentence-Indexed Citation Validation (
validateCitations): Facts derived from Wikipedia must cite the exact 1-indexed sentence number from the Wikipedia lead extract. Out-of-bounds citations or fabricated sentences are dropped. - Strict Zod Schemas:
All agent responses enforce structured JSON via Vercel AI SDK
generateObjectwith Zod schemas (IdentificationSchema,FactsSchema,WalkDispatchSchema).
4. Privacy & Anonymization Guardrails
- Canvas EXIF Scrubbing (
lib/camera.ts): Uploaded photos are rasterized to an HTML5 Canvas on the client before saving or dispatching, wiping 100% of EXIF, GPS coordinates, device serials, and timestamps. - Coarse Coordinate Truncation (
app/api/identify/route.ts): When location context is sent to the AI for seasonal/regional hints, coordinates are rounded to 1 decimal place (~11 kmradius):Precise GPS breadcrumbs never leave the device. - Local-First Architecture:
Walk tracks, audio recordings, and field guide entries are saved in browser IndexedDB via Dexie (
lib/db.ts).
5. Availability & Offline Degradation
Every AI agent route includes fallback mocks when API keys are not provided or upstream model calls fail:
- Identification returns verified offline specimen candidates (
MOCK_IDENTIFY_RESPONSE). - Facts generation returns offline Wikipedia extracts (
getFallbackFact). - Walk dispatch synthesizes an offline atmospheric field summary (
getFallbackDispatch).
Minor Areas for Future Hardening
- User Note Prompt Injection Protection in Dispatch:
In
app/api/walk/dispatch/route.ts, user-recorded voice transcripts are injected directly into the prompt string:While output is constrained byWalkDispatchSchema, sanitizing or truncating user notes prevents adversarial prompt injection. - Payload Size Clamping:
Adding an explicit size check on incoming base64 image strings in
app/api/identify/route.ts(e.g. max 5 MB) prevents excessive memory consumption.
Here is a breakdown of the specific AI agents operating in Treads—their roles, underlying models, input/output contracts, and where they live in the application:
1. The Field Botanist & Taxonomist Agent
- Endpoint:
/api/identify - Model: Configured via
IDENTIFY_MODEL_ID(defaults to Google AI Studiogemma-4-26b-a4b-itor Gemini Vision) - Role: Acts as an expert naturalist companion reviewing raw photographs taken on the trail.
- Input Context:
- Base64 image payload (Canvas-stripped of all EXIF/GPS).
- Coarse regional hint: latitude & longitude rounded to 1 decimal place (
~11 kmresolution). - Month of observation (
1–12) to provide phenological context (e.g. spring bloom vs winter dormancy).
- Behavior & Output Contract (
IdentificationSchema):- Living vs Inanimate Classifier: First validates if the photo is actually wild or domestic nature. If it sees humans, vehicles, pavement, or inanimate objects, it refuses with
isLivingOrganism: falseand an educational explanation. - Candidate Ranking: Produces up to 3 candidate species ordered by likelihood with confidence scores (
Likely,Possible,Unsure), common vernacular name, binomial scientific name, taxonomic group (tree,flower,plant,bird,insect,fungus,animal), and the exact Wikipedia title. - External Verification Loop: Before returning to the UI, the candidate list is validated against the Wikipedia Action API (
verifyWikipediaTaxon) to ensure the taxon is a recognized biological entity.
- Living vs Inanimate Classifier: First validates if the photo is actually wild or domestic nature. If it sees humans, vehicles, pavement, or inanimate objects, it refuses with
2. The Ecological Educator & Micro-Observer Agent
- Endpoint:
/api/facts - Model: Configured via
FACTS_MODEL_ID(defaults togemma-4-26b-a4b-itor Gemini) - Role: A grounded science communicator that synthesizes verified Wikipedia knowledge into digestible trail-side field guide cards.
- Input Context:
- Wikipedia article lead section retrieved live and segmented into discrete numbered sentences (
1..N). - Common name and scientific binomial.
- Wikipedia article lead section retrieved live and segmented into discrete numbered sentences (
- Behavior & Output Contract (
FactsSchema):- Overview Summary: A 2–3 sentence overview of the species (max 40 words).
- Grounded Fact Bullets: Up to 3 biological/ecological facts. Each fact is strictly required to cite the exact 1-indexed sentence number in the Wikipedia text it was derived from.
- "Look Closely" Sensory Prompt: A 1-sentence physical prompt directing the walker's eyes to a subtle detail right in front of them (e.g. examining leaf underside veining, bark ridge depth, pollen sac coloration, or spore gill attachment).
- Safety Gate: Filtered through
containsSafetyViolationsto scrub any hallucinated culinary, medicinal, foraging, or edibility claims.
3. The Naturalist Chronicler & Ecological Web Agent
- Endpoint:
/api/walk/dispatch - Model:
gemma-4-26b-a4b-it/ Gemini - Role: Inspired by field essayists like Aldo Leopold, this agent acts as a reflective chronicler that reviews an entire completed walk expedition and reveals the hidden connections between observed species.
- Input Context:
- Full list of confirmed species recorded during the walk.
- Walk telemetry: total distance covered (km) and active duration (minutes).
- Transcribed voice field notes recorded by the walker along the route.
- Behavior & Output Contract (
WalkDispatchSchema):- Field Naturalist Dispatch: A poetic 2–3 sentence prose dispatch capturing the atmosphere of the journey, weather context from notes, and the overarching character of the landscape explored.
- Observed Ecological Web (
connections): Analyzes the observed species pairs to find real, verified ecological relationships (such as mycorrhizal fungal partnerships with host trees, caterpillar host plants, avian seed dispersers, or pollinator blooms). It is strictly forbidden from hallucinating fictional interactions.
4. The Auditory Transcription Agent
- Endpoint:
/api/transcribe - Engine: ElevenLabs Scribe STT (
scribe_v1) - Role: Hands-free trail audio transcriber.
- Input Context:
- WebM audio streams recorded directly from the user's microphone during the walk.
- Language code hint (defaults to
en).
- Behavior & Output:
- Converts spoken voice notes into clean text transcripts.
- Extracts word-level timestamps (
words: Array<{ text, start, end }>), enabling synchronized audio scrubbing and karaoke-style text highlight reels in the journal review.
5. The Trail Narrator Agent
- Endpoint:
/api/speak - Engine: ElevenLabs Multilingual TTS (
eleven_multilingual_v2) - Role: A calm, hands-free field audio guide.
- Voice Character: Rachel (
21m00Tcm4TlvDq8ikWAM), selected for a warm, contemplative, calm tempo that fits outdoor nature immersion. - Behavior & Output:
- Streams synthesized speech audio for verified facts and species summaries so walkers can keep their eyes on the trees and trail rather than staring at a screen.
- Includes length caps (max 2,000 characters) and HTTP caching (
Cache-Control: public, max-age=86400) to avoid duplicate generation costs.
6. The Pedestrian Route Synthesis Agent
- Endpoint:
/api/route - Engine: OpenRouteService Pedestrian Routing Engine with local synthetic geometric fallbacks (
lib/route.ts) - Role: An automated expedition planner.
- Input Context:
- Starting GPS coordinate (only the starting point is ever transmitted).
- Target distance (1 km, 2 km, or 3 km).
- Optional custom stop waypoints or polygonal vertices.
- Behavior & Output:
- Generates closed round-trip pedestrian loops optimized for walking paths, footways, and green spaces while avoiding highways and dead ends.
- Automatically calculates synthetic geometric loops if external routing APIs are unavailable or offline.
what framework are those agents based on? adk or eve or plain md files ? if md files why not framework used?
What Framework Are Those Agents Based On?
The in-app AI agents are not based on heavy multi-agent runtime frameworks like ADK (Agent Development Kit) or Eve, nor are they prompt-injection Markdown (.md) files loaded at runtime.
Instead, they are built directly on the Vercel AI SDK (ai v7 + @ai-sdk/google) with Zod schema-enforced structured generation (generateObject) executed inside Next.js App Router serverless Route Handlers.
Specifically:
- Core Orchestrator:
ai(import { generateObject } from 'ai') - Provider Adapter:
@ai-sdk/google(import { createGoogleGenerativeAI } from '@ai-sdk/google') - Schema Contracts:
zod(z.object({ ... })) - Verification Middleware: Custom TypeScript pipelines (e.g.
lib/facts-safety.ts,lib/wikipedia.ts,lib/rate-limit.ts)
Why Not ADK, Eve, or Heavy Multi-Agent Frameworks?
-
Deterministic Structured JSON over Open-Ended Chat Loops:
- The app does not need conversational autonomous agent loops that wander through multi-turn decision trees.
- It needs strict, single-turn typed contracts (e.g., exactly 3 candidates with verified Wikipedia slugs, or exactly 3 facts citing Wikipedia sentence numbers).
generateObjectwith Zod guarantees that the model outputs type-safe JSON matching TypeScript interfaces at the compiler level.
-
Serverless Edge Performance & Latency:
- Frameworks like ADK or Eve introduce Python runtimes, Docker containers, stateful memory servers, and orchestration overhead.
- Using the Vercel AI SDK runs natively in Vercel/Node.js serverless functions with zero cold-start bloat, executing requests in sub-second response times right to the mobile client.
-
Client-Side Privacy & Local-First Philosophy:
- Treads is designed so that user GPS trails, photos, and life-list journals live privately in the browser's IndexedDB (
lib/db.ts). - Heavy agent frameworks typically require cloud session persistence, remote state storage, and user profiling, which conflicts directly with the app's privacy-first, offline-capable architecture.
- Treads is designed so that user GPS trails, photos, and life-list journals live privately in the browser's IndexedDB (
-
Programmatic Middleware & Guardrails:
- By implementing the pipeline in TypeScript, safety checks (such as the regex scrubber in
lib/facts-safety.tsdropping edibility/poisoning claims and Wikipedia Action API verification) run synchronously in memory as pure code without relying on an agent remembering its instructions.
- By implementing the pipeline in TypeScript, safety checks (such as the regex scrubber in
Where Do .md Files Fit In?
If you see .md files in the repository (such as AGENTS.md, .planning/ files, or custom skill definitions):
- Those are developer & coding assistant instructions (used by tools like Claude Code, Antigravity, or Copilot during the development process).
- They are not loaded by the runtime app to drive the in-app AI features. The live app's behavior is driven entirely by TypeScript code, Zod schemas, and structured prompts in
app/api/.
Yes, API keys are strictly guarded in Treads, with virtually zero risk of leaking to the client or public.
A comprehensive audit of the codebase confirms the following security safeguards:
1. No Client-Side Exposure (NEXT_PUBLIC_ Audit)
In Next.js, environment variables are only embedded into browser JavaScript bundles if they are prefixed with NEXT_PUBLIC_.
- Audit result: None of the secret keys (
GOOGLE_GENERATIVE_AI_API_KEY,ELEVENLABS_API_KEY,ORS_API_KEY,UPSTASH_REDIS_REST_TOKEN) use theNEXT_PUBLIC_prefix. - The browser bundle never has access to or knowledge of these variables.
2. Complete Server-Side Gateway Isolation
All vendor communication takes place exclusively in Node.js serverless route handlers:
- Google AI Studio calls occur strictly inside
app/api/identify,app/api/facts, andapp/api/walk/dispatch. - ElevenLabs calls occur strictly inside
app/api/transcribeandapp/api/speak. - OpenRouteService calls occur strictly inside
app/api/route.
The client UI components only make fetch('/api/...') calls to your own backend proxies.
3. Git History & Environment Hygiene
- Never Committed: Neither
.envnor.env.localhas ever been checked into Git history. .gitignore: Configured to ignore.env,.env*.local, certificates, and local agent logs..env.example: The only tracked env file in the repo contains only blank placeholder definitions with zero actual credentials.- No Hardcoded Keys: Automated regex scans found zero hardcoded secrets or API tokens in the source code or test scripts.
4. Error Message Sanitization
- Production endpoints never reflect raw upstream SDK errors or HTTP authorization headers back to the browser; in case of model error, they gracefully return generic user-friendly messages or offline mock fallbacks.
- Development spike routes (
app/api/spike/ai/route.ts) actively scrub and redact any potential query-string tokens orAIza...key patterns before returning responses.
5. Quota & Denial-of-Service Protection
Even though your backend acts as a shield for your API keys, an attacker hitting your endpoints directly could consume your vendor quota. This is guarded by:
- Strict per-IP rate limiting via
checkRateLimit()(30–60 calls/day per IP). - Automated HTTP 429 throttling with
Retry-Afterheaders.